AI智能
改变未来

使用Hot Chocolate和.NET 6构建GraphQL应用(3) —— 实现Query基础功能


系列导航

使用Hot Chocolate和.NET 6构建GraphQL应用文章索引

需求

在本文中,我们通过一个简单的例子来看一下如何实现一个最简单的GraphQL的接口。

实现

引入Hot Chocolate依赖包

由于我打算将GraphQL的相关逻辑放到Applicaiton层,并在Application和Api项目中使用,所以在该项目中引入以下依赖包

# Hot Chocolate在.NET Web应用中使用的主要Nuget包HotChocolate.AspNetCore# Hot Chocolate集成EntityFramework Core底层ORM框架的Nuget包HotChocolate.Data.EntityFramework# Hot Chocolate的一些属性定义扩展HotChocolate.Data# 一个可视化的GraphQL Schema中间件GraphQL.Server.Ui.Voyager

添加Resolver

Api

项目中添加文件夹

GraphQL

用于存放GraphQL接口相关的定义,并新建

Query.cs

文件,我们在这里定义一个接口:

  • Query.cs
namespace PostGraphi.Api.GraphQL;public class Query{// [Service]是Hot Chocolate提供的用于获取依赖注入对象的属性public IQueryable<Post> GetPosts([Service] IRepository<Post> repository) => repository.GetAsQueryable();}

需要在

GlobalUsings.cs

中添加以下命名空间:

  • GlobalUsings.cs
global using HotChocolate;global using PostGraphi.Domain.Post.Entities;

添加依赖注入

  1. 添加GraphQL的服务:
builder.Services.AddGraphQLServer().AddQueryType<Query>();
  1. 添加GraphQL终结点配置和Voyager中间件
app.UseHttpsRedirection();// 添加GraphQL终结点配置app.UseRouting().UseEndpoints(endpoints =>{endpoints.MapGraphQL();});// 添加Voyager中间件并配置URLapp.UseGraphQLVoyager(new VoyagerOptions { GraphQLEndPoint = "/graphql" }, "/graphql-voyager");app.UseAuthentication();app.UseAuthorization();

验证

运行

Api

项目,首先我们访问地址:https://localhost:7194/graphql-voyager 查看Voyager的主页:

可以看到我们目前只有一个schema,名称叫做posts,该接口所关联的实体以及实体关联的其他实体组成的图非常清楚地显示出来了。这张图上我们能看到

DomainEvents

也显示出来了,但这不是我们想要的,这个问题我们稍后来解决。

再去查看Hot Chocolate官方提供的随程序一起启动的

Banana Cake Pop

主页:https://localhost:7194/graphql/

在这个页面上我们可以查看具体的Schema Definition和全部的GraphQL Server所维护的类型定义。也可以从

Operations

标签页直接发起GraphQL请求。

query {posts {id,title,author,comments {content}tags {name}}}

如果使用API Client发起GraphQL请求,注意请求是

POST
https://localhost:7194/graphql

,Body内容是GraphQL Query,像这样:

在执行请求之后,我们先来看看控制台的EFCore日志输出:

SELECT "p"."Id", "p"."Abstraction", "p"."Author", "p"."Content", "p"."Created", "p"."CreatedBy", "p"."LastModified", "p"."LastModifiedBy", "p"."Link", "p"."PublishedAt", "p"."Title"FROM "Posts" AS "p"

敏锐的小伙伴可能会发现,这个sql里并没有看到和Comments和Tags相关的Join之类的操作,下面的通过

Banana Cake Pop

请求响应也同样能说明这个问题:

在这个返回结果里,我们至少能看到两类问题:一是Comments和Tags这种一对多和多对多的关联表数据并没有同时返回;二是返回似乎没有排序。这两个问题我们会在后面的文章里逐个去解决。

不管怎么样,我们的第一个GraphQL接口已经调用成功了。下面来解决上面说到的

DomainEvents

的问题。

改进

因为我们默认使用了

Annotation First

方式去构建接口,并且是直接使用的实体对象,并没有做任何配置,因为我并不想将业务相关的接口属性直接配置到我的Domain Model上,这个时候就需要使用

Code First

方式去为

Post

类定义对应的GraphQL类。

Api/GraphQL

中新建文件夹

Types

并创建

PostType.cs

,让它继承自Hot Chocolate提供的

ObjectType<T>

类型,并重写

Configure

方法:

  • PostType.cs
namespace PostGraphi.Api.GraphQL.Types;public class PostType : ObjectType<Post>{protected override void Configure(IObjectTypeDescriptor<Post> descriptor){descriptor.Description("Represents Post Entity Type.");// 构建schema时忽略这个字段descriptor.Field(d => d.DomainEvents).Ignore();}}

需要在

GlobalUsings.cs

中引入命名空间:

  • GlobalUsings.cs
global using HotChocolate.Types;

最后在依赖注入的地方添加Type即可:

builder.Services.AddGraphQLServer().AddQueryType<Query>().AddType<PostType>();

重新运行程序,我们在Voyager主页上查看,DomainEvents已经消失了:

总结

在本文中我们实现了一个最简单的GraphQL接口,并且使用了Hot Chocolate提供的两种方式

Annotation First

Code First

实现了功能。其实关于

Code First

方式还有一个比较重要的概念叫做

Resolver

我们在文章演示中没有涉及,这个概念可以理解为通过

Code First

方式去定义GraphQL对象时,我们可以使用

ResolveWith

来指定使用什么Resolver去获取数据。更多的配置方法可以参考官方文档:Resolvers。

本文我们还留下了两个问题,下一篇文章将会实现关联实体对象的获取方式。

参考文章

  1. Resolvers
赞(0) 打赏
未经允许不得转载:爱站程序员基地 » 使用Hot Chocolate和.NET 6构建GraphQL应用(3) —— 实现Query基础功能