GraphQL query in .NET Core
使用 HotChocolate 在 ASP.NET Core Web API 项目中提供 GraphQL 查询服务
添加依赖
.NET 平台上的 GraphQL 服务有 GraphQL.net 和 HotChocolate
HotChocolate 提供了更多的特性和扩展,比如过滤、排序、分页、订阅、批量操作等,并且可以自动将 .NET 类型转换为 GraphQL 类型
如果想要更多的控制和灵活性,可以选择 GraphQL.net;如果想要更多的便利和功能,则可以选择 HotChocolate
配置 HotChocolate 会更简单一些
dotnet add package HotChocolate.Data
dotnet add package HotChocolate.AspNetCore
dotnet add package HotChocolate.Abstractions
实现查询
- 在 Persistence 层创建
TodoListQuery.cs
,在这里实现需要的查询
public class TodoListQuery
{
[UsePaging(IncludeTotalCount = true, DefaultPageSize = 10)]
public IQueryable<TodoList> GetTodoLists([Service] ApplicationDbContext dbContext)
=> dbContext.TodoLists.AsQueryable();
public IQueryable<TodoList> GetTodoList(int id, [Service] ApplicationDbContext dbContext)
=> dbContext.TodoLists.Include(x => x.Items).Where(x => x.Id == id);
// ...
}
Use IncludeTotalCount = true
to show the total count of the output result.
Use int id
as input param.
- 若使用 MediatR,则在 API 层传递 command,并实现相应的 handler
public class TodoListQuery
{
[UsePaging(IncludeTotalCount = true, DefaultPageSize = 10)]
[UseFiltering]
public async Task<List<TodoListDto>> GetTodoLists([Service] IMediator mediator)
=> await mediator.Send(new GetTodosQueryGraph(null));
[UsePaging(IncludeTotalCount = true, DefaultPageSize = 10)]
public async Task<List<TodoListDto>> GetTodoLists(GetTodosQueryGraph query, [Service] IMediator mediator)
=> await mediator.Send(query);
// ...
}
public record GetTodosQueryGraph(string? Title) : IRequest<List<TodoListDto>>;
public class GetTodosQueryGraphHandler : IRequestHandler<GetTodosQueryGraph, List<TodoListDto>>
{
private readonly IApplicationDbContext _context;
private readonly IMapper _mapper;
public GetTodosQueryGraphHandler(IApplicationDbContext context, IMapper mapper)
{
_context = context;
_mapper = mapper;
}
public async Task<List<TodoListDto>> Handle(GetTodosQueryGraph request, CancellationToken cancellationToken)
{
return await _context.TodoLists
.AsNoTracking()
.Where(x => x.Title.Contains(request.Title!))
.ProjectTo<TodoListDto>(_mapper.ConfigurationProvider)
.OrderBy(t => t.Title)
.ToListAsync(cancellationToken);
}
}
注入配置
- 注入 GraphQL 服务配置
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddGraphQLServer()
.AddQueryType<TodoListQuery>()
.AddFiltering();
仅在开发环境下启用 Banana Cake Pop GraphQL IDE
app.MapGraphQL().WithOptions(new GraphQLServerOptions()
{
Tool = { Enable = builder.Environment.IsDevelopment() }
});
app.Run();
测试查询
访问 /graphql
进行测试
request
query TodoLists { todoLists(first: 3, where: {title: {contains: "occaecat"}}){ totalCount nodes{ id title } pageInfo{ hasPreviousPage startCursor endCursor hasNextPage } } }
repsonse
{ "data": { "todoLists": { "totalCount": 18, "nodes": [ { "id": 3, "title": "occaecat m" }, { "id": 4, "title": "occaecat rm" }, { "id": 5, "title": "occaecat; rm" } ], "pageInfo": { "hasPreviousPage": false, "startCursor": "MA==", "endCursor": "Mg==", "hasNextPage": true } } } }
Getting started with GraphQL and HotChocolate | Microsoft Learn