如何用.NET的Hot Chocolate自动生成GraphQL模型CRUD API?
在Hot Chocolate中简化基础CRUD查询的实现方案
一、利用Hot Chocolate EF Core集成自动生成查询
Hot Chocolate原生支持与EF Core深度集成,可自动为DbContext中的所有实体生成基础查询(列表、单条按ID查询),无需手动编写重复代码。
实现步骤:
- 安装NuGet包:
HotChocolate.Data.EntityFramework - 在Program.cs中配置GraphQL服务时启用EF Core查询支持:
// Program.cs using Microsoft.EntityFrameworkCore; using HotChocolate.Data.EntityFramework; var builder = WebApplication.CreateBuilder(args); // 注册DbContext builder.Services.AddDbContext<AppDbContext>(options => options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection"))); // 配置GraphQL服务 builder.Services.AddGraphQLServer() .AddQueryType() .AddEntityFrameworkQueryableMethods() // 启用EF Core自动查询生成 .AddFiltering() // 可选:添加过滤功能 .AddSorting(); // 可选:添加排序功能 var app = builder.Build(); // 映射GraphQL端点 app.MapGraphQL(); app.Run();
配置完成后,Hot Chocolate会自动为AppDbContext中的每个DbSet生成对应的查询字段(如questions、answers),同时默认支持按ID查询单条数据(如question(id: "1")),完全替代手动编写的Query类方法。
二、用泛型方法简化手动Query类(保留自定义控制权)
如果需要保留Query类的自定义空间,可通过泛型方法减少重复代码:
using Microsoft.EntityFrameworkCore; using HotChocolate; namespace BackEnd { public class Query { // 泛型方法处理所有实体的列表查询 public async Task<List<TEntity>> GetAll<TEntity>([Service] AppDbContext dbContext) where TEntity : class { return await dbContext.Set<TEntity>().ToListAsync(); } } }
若需要为每个实体指定单独的查询名称(如GetQuestions而非GetAll),可使用类型扩展复用泛型逻辑:
namespace BackEnd { public static class QueryExtensions { public async Task<List<Question>> GetQuestions([Service] AppDbContext dbContext) => await dbContext.Set<Question>().ToListAsync(); public async Task<List<Answer>> GetAnswers([Service] AppDbContext dbContext) => await dbContext.Set<Answer>().ToListAsync(); public async Task<List<User>> GetUsers([Service] AppDbContext dbContext) => await dbContext.Set<User>().ToListAsync(); // 其他实体同理,代码量远低于手动重复编写 } }
然后在Program.cs的GraphQL配置中添加类型扩展:
builder.Services.AddGraphQLServer() // ... 其他配置 .AddTypeExtension<QueryExtensions>();
三、使用T4模板自动生成Query类代码
如果需要完全自定义生成的代码结构,可借助.NET的T4模板批量生成Query类方法:
创建QueryGenerator.tt文件,内容如下:
<#@ template language="C#" #> <#@ assembly name="System.Core" #> <#@ import namespace="System.Linq" #> <#@ output extension=".cs" #> using Microsoft.EntityFrameworkCore; namespace BackEnd { public class Query { <# // 手动维护需要生成查询的实体列表 var entityTypes = new[] { "Question", "Answer", "User", "House", "Cat", "Dogs" }; foreach (var entity in entityTypes) { // 处理复数名称(可根据实际情况调整) var pluralName = entity switch { "House" => "Houses", _ => entity.EndsWith("s") ? entity : $"{entity}s" }; #> public async Task<List<<#= entity #>>> Get<#= pluralName #>(AppDbContext dbContext) { return await dbContext.<#= pluralName #>.ToListAsync(); } <# } #> } }
保存后,Visual Studio会自动生成对应的QueryGenerator.cs文件,后续新增实体只需更新entityTypes数组即可自动生成代码。
内容的提问来源于stack exchange,提问作者Thiệu Trần Quốc
相关产品推荐
相关产品推荐

