使用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;
添加依賴注入
- 添加GraphQL的服務:
builder.Services
.AddGraphQLServer()
.AddQueryType<Query>();
- 添加GraphQL終結點配置和Voyager中間件
app.UseHttpsRedirection();
// 添加GraphQL終結點配置
app.UseRouting().UseEndpoints(endpoints =>
{
endpoints.MapGraphQL();
});
// 添加Voyager中間件並配置URL
app.UseGraphQLVoyager(new VoyagerOptions { GraphQLEndPoint = "/graphql" }, "/graphql-voyager");
app.UseAuthentication();
app.UseAuthorization();
驗證
運行Api
項目,首先我們訪問地址://localhost:7194/graphql-voyager 查看Voyager的主頁:
可以看到我們目前只有一個schema,名稱叫做posts,該介面所關聯的實體以及實體關聯的其他實體組成的圖非常清楚地顯示出來了。這張圖上我們能看到DomainEvents
也顯示出來了,但這不是我們想要的,這個問題我們稍後來解決。
再去查看Hot Chocolate官方提供的隨程式一起啟動的Banana Cake Pop
主頁://localhost:7194/graphql/
在這個頁面上我們可以查看具體的Schema Definition和全部的GraphQL Server所維護的類型定義。也可以從Operations
標籤頁直接發起GraphQL請求。
query {
posts {
id,
title,
author,
comments {
content
}
tags {
name
}
}
}
如果使用API Client發起GraphQL請求,注意請求是POST
//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。
本文我們還留下了兩個問題,下一篇文章將會實現關聯實體對象的獲取方式。