C# / .NET:graphql-net(将 GraphQL 转为 IQueryable)
graphql-github-io-zh-Hans生态项目与库
C# / .NET:graphql-net(将 GraphQL 转为 IQueryable)
概述
graphql-net 是一个面向 C# / .NET 的开源库,核心功能是将 GraphQL 查询直接转换为 IQueryable,从而让 GraphQL 查询能够与 Entity Framework 等 LINQ 提供程序无缝协作。通过这种转换,你可以在不牺牲性能的前提下,让客户端灵活地指定需要的数据字段,而服务端则使用数据库原生查询执行,避免加载不必要的数据。
核心特性
- GraphQL → IQueryable 转换:自动将 GraphQL 选择集映射为 LINQ 表达式,生成可组合的
IQueryable。 - 与 Entity Framework 集成:直接作用于
DbSet或自定义IQueryable,查询在数据库端执行。 - 类型安全:利用 C# 泛型和表达式树,在编译期尽可能发现字段映射错误。
- 轻量、无侵入:可以只用于查询解析层,无需替换现有业务逻辑。
- 支持自定义解析:允许你为复杂字段提供自定义
Resolve委托。
工作原理
graphql-net 接收一个 GraphQL 查询请求,将其解析为抽象语法树(AST),然后遍历查询的选择集,根据目标类型(例如 IQueryable<Customer>)构建对应的 Expression<Func<T>>,最终生成一个新的 IQueryable。这样,返回的数据结构由客户端指定的字段决定,同时仍保持 LINQ 的延迟执行特性。
快速开始
以下示例演示如何将 GraphQL 查询应用于 IQueryable<Order>。
csharp
using GraphQL;
using GraphQL.Types;
using GraphQLNet;
using System.Linq;
// 定义数据模型
public class Order
{
public int Id { get; set; }
public string ProductName { get; set; }
public decimal Total { get; set; }
public Customer Customer { get; set; }
}
public class Customer
{
public string Name { get; set; }
public string Email { get; set; }
}
定义 GraphQL 类型:
csharp
public class OrderType : ObjectGraphType<Order>
{
public OrderType()
{
Field(x => x.Id);
Field(x => x.ProductName);
Field(x => x.Total);
Field<CustomerType>("customer", resolve: ctx => ctx.Source.Customer);
}
}
public class CustomerType : ObjectGraphType<Customer>
{
public CustomerType()
{
Field(x => x.Name);
Field(x => x.Email);
}
}
使用 IQueryable 执行 GraphQL 查询:
csharp
public async Task<string> ExecuteQueryAsync(IQueryable<Order> orders, string graphQlQuery)
{
var schema = new Schema { Query = new OrderQuery() };
var result = await schema.ExecuteAsync(_ =>
{
_.Query = graphQlQuery;
_.Root = orders; // 传入 IQueryable
});
return Newtonsoft.Json.JsonConvert.SerializeObject(result);
}
其中 OrderQuery 定义根查询字段:
csharp
public class OrderQuery : ObjectGraphType
{
public OrderQuery()
{
Field<ListGraphType<OrderType>>(
"allOrders",
resolve: context =>
{
// context.Source 实际上是传入的 IQueryable
var query = context.Source as IQueryable<Order>;
return query; // graphql-net 将自动转换为 IQueryable 并处理选择集
});
}
}
与实体框架结合
假设使用 EF Core,你可以直接将 DbContext 的 DbSet<T> 作为根:
csharp
using var db = new AppDbContext();
var query = db.Orders.AsQueryable();
// 执行 GraphQL 查询,数据库只返回所选字段
graphql-net 生成的表达式会被 EF 翻译为 SQL,避免将整个实体加载到内存。
高级配置
- 字段重命名:可以通过
Field(x => x.Property).Name("graphqlName")来自定义 GraphQL 字段名。 - 忽略字段:使用
Field<ListGraphType<OrderType>>("orders", resolve: ...)时,未被选择的字段不会体现在 IQueryable 的投影中。 - 中间件/过滤器:可结合
WithVariables、Authorize等 GraphQL.NET 扩展实现权限控制。
适用场景
- 需要为现有 LINQ 数据源快速暴露 GraphQL API。
- 希望避免手写大量 DTO 和映射代码。
- 需要确保查询在数据库层执行,避免 N+1 问题。
注意事项
- 仅支持同步/异步
IQueryable,不支持IEnumerable的完整树转换(需自行物化)。 - 复杂父子关系可能需要额外调整表达式,建议先测试生成的 SQL。
- 项目目前维护频率不高,建议评估后使用,或参考其实现自行扩展。
项目地址
- GitHub: chkimes/graphql-net
- 原始描述: Convert GraphQL to IQueryable
帮助我们改进文档
发现翻译问题或内容错误?请告诉我们。
