关于 hotchocolate-best-practices
hotchocolate-best-practices 是用于在 .NET 中实现或审查 HotChocolate GraphQL 服务端的指导技能,面向 16.6 及更新版本。内容侧重基于属性的 C# 实现、源生成 DataLoader 和游标分页。
主要功能
- 01基于属性实现 C# Schema
- 02通过源生成 DataLoader 访问数据
- 03基于 QueryContext 的投影
- 04带确定性排序的游标分页
- 05涵盖解析器、变更、过滤和排序
适用场景
- 01实现可避免 N+1 查询的解析器
- 02使用 DataLoader 批量处理根查询
- 03构建有序的游标分页字段
- 04审查 HotChocolate 16.6+ 服务端配置和代码
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ chillicream/ agent-skills --skill hotchocolate-best-practices安装后在 Claude Code 中输入/hotchocolate-best-practices确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/dataloaders.mdfiltering.mdmutations.mdpagination.mdresolvers.mdserver-setup.mdsorting.mdsubgraph.md详细介绍
HotChocolate 最佳实践
你正在使用 .NET 实现或审查 HotChocolate GraphQL 服务。所有指导均适用于 HotChocolate 16.6 或更高版本——未经查阅迁移指南,不要将其应用于 v15 或更早版本的代码库。本指南定义了 ChilliCream 对代码风格的预期。内容涵盖实现——解析器、数据访问、DataLoader、分页。Schema 设计(SDL 结构、命名、可空性)属于配套指南 graphql-schema-design;如果任务同时涉及设计和实现,请同时使用两者。
核心原则
-
优先采用实现方式。 编写纯 C# 代码——使用
[QueryType]、[MutationType]、[ObjectType<T>]、[DataLoader]等特性的静态解析器类——并让 HotChocolate 推断 schema。不要使用 schema-first SDL 绑定;只有在特性无法表达时,才使用 descriptor/Configure覆盖。 -
所有数据访问都通过 DataLoader。 关系解析器(任何获取数据的非根字段)绝不直接查询
DbContext或存储库,而是调用 DataLoader。直接查询会产生 N+1 次加载,并绕过请求范围内的缓存。 -
顶层
byId字段也使用 DataLoader。 根查询可以批处理:客户端可在单个操作中使用字段别名进行批处理,也可在多个操作之间使用请求/变量批处理。根解析器若直接访问数据库,就会失去这种合并请求的能力。 -
DataLoader 由源代码生成器生成。 编写带有
[DataLoader]注解的静态方法;不要手动编写继承自BatchDataLoader/GroupedDataLoader的类。生成器会生成类、接口和注册代码。 -
投影通过
QueryContext<T>传递。 每个 DataLoader 都接受QueryContext<TValue>参数,以便调用方将所选字段传递到数据库,并始终将键固定加入投影(query.Include(x => x.Id)),确保收窄投影后键仍然存在。相应地,每个读取父对象属性的解析器都要使用[Parent(requires: nameof(...))]声明这些属性,以便投影保留这些字段。 -
分页采用基于游标的方式,并具有顺序。 分页字段使用
PagingArguments+ToPageAsync/ToBatchPageAsync;每个分页查询都必须采用确定的排序,并以键作为最后排序条件;非根类型上的分页必须通过批量分页 DataLoader 实现。绝不使用偏移分页——相对游标已能满足跳转到指定页的需求。
项目设置
每个 HotChocolate 项目都会以仅分析器的方式引用源代码生成器包,并明确指定模块:
<PackageReference Include="HotChocolate.AspNetCore" />
<PackageReference Include="HotChocolate.Data" />
<PackageReference Include="HotChocolate.Types.Analyzers">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
Properties/ModuleInfo.cs 只包含一行,将模块命名为对应的领域名称——切勿依赖根据程序集名称派生的默认值:
[assembly: Module("RecommendationTypes")]
这会指定用于注册项目中所有 GraphQL 相关类型的方法名称——包括类型和 DataLoader。通用服务设置放在共享的 AddDefaultSettings 扩展方法中,让主要调用链只展示特定于 schema 的选项——请参阅 references/server-setup.md:
builder
.AddGraphQL()
.AddDefaultSettings()
.AddRecommendationTypes();
参考文件索引
包含详细规则及错误与正确示例对照。仅加载当前任务涉及的内容。
| 参考文件 | 加载时机 |
|---|---|
| references/dataloaders.md | 涉及任何 DataLoader、任何获取数据的解析器、任何 N+1 问题,或任何 byId 字段时 |
| references/pagination.md | 涉及任何分页字段、[UseConnection]、PagingArguments、连接/页面类型,或集合排序时 |
| references/resolvers.md | 涉及使用 [ObjectType<T>] 扩展实体、[BindMember]、[Parent(requires:)]、根类型类或字段命名时 |
| references/subgraph.md | 项目是子图时——可通过构建器链中的 .AddSourceSchemaDefaults() 或 schema-settings.json 文件判断。涵盖 byId 字段上的 [Lookup]、实体引用、成本强制执行,以及将节点用作查找字段 |
| references/server-setup.md | 涉及新项目、Program.cs / 构建器链、csproj 包、[assembly: Module] 或 AddDefaultSettings 时 |
| references/mutations.md | 涉及任何变更、[MutationType]、变更约定、[Error] 或负载/输入形状时 |
| references/filtering.md | 涉及任何 UseFiltering 用法、筛选输入类型,或判断字段是否应支持筛选时 |
| references/sorting.md | 涉及任何 UseSorting 用法、排序输入类型,或判断客户端是否可以排序字段时 |
随着技能不断完善,将添加更多参考资料。