C# 使用GraphQL.EntityFramework公开多对多关系
我有一个相当直接的.NET Core EF模型,由一个SQL Server数据库支持,我正在通过.NET Core Web API中的GraphQL公开该模型,并使用该模型构建 我有一些多对多的关系,比如: 为清晰起见,实体模型已删除此表单中的不相关位:C# 使用GraphQL.EntityFramework公开多对多关系,c#,entity-framework,graphql,C#,Entity Framework,Graphql,我有一个相当直接的.NET Core EF模型,由一个SQL Server数据库支持,我正在通过.NET Core Web API中的GraphQL公开该模型,并使用该模型构建 我有一些多对多的关系,比如: 为清晰起见,实体模型已删除此表单中的不相关位: public class StoreEntity { [Key] public int StoreId { get; set; } public string Name { get; set; } // etc
public class StoreEntity
{
[Key]
public int StoreId { get; set; }
public string Name { get; set; }
// etc...
public List<StoreCategoryEntity> Categories { get; set; }
}
public class StoreCategoryEntity
{
[Required]
public int StoreId { get; set; }
[Required]
public int CategoryId { get; set; }
public CategoryEntity Category { get; set; }
}
public class CategoryEntity
{
[Key]
public int CategoryId { get; set; }
public string Name { get; set; }
}
使用GraphQL.EntityFramework,典型的对象图类型如下:这是构造函数:
public StoreType(IEfGraphQLService<MyDbContext> efGraphQlService) : base(efGraphQlService)
{
Field(x => x.StoreId).Description("The store ID");
Field(x => x.Name).Description("The store name");
// ...
AddNavigationListField(
name: "categories",
resolve: context => context.Source.Categories);
}
这很好,但比我希望的要复杂一些。我希望导航列表字段的类型为Category,而不是StoreCategory。我试过这个:
public StoreType(IEfGraphQLService<MyDbContext> efGraphQlService) : base(efGraphQlService)
{
Field(x => x.StoreId).Description("The store ID");
Field(x => x.Name).Description("The store name");
AddNavigationListField(
name: "categories",
resolve: context => context.Source.Categories.Select(x => x.Category));
}
…但此代码将为每个存储创建单独的DB往返,这正是GraphQL.EntityFramework设计用来避免的那种情况。此功能:
public StoreType(IEfGraphQLService<MyDbContext> efGraphQlService) : base(efGraphQlService)
{
Field(x => x.StoreId).Description("The store ID");
Field(x => x.Name).Description("The store name");
// ...
AddNavigationListField(
name: "categories",
resolve: context => context.Source.Categories.Select(x => x.Category),
includeNames: new[] { "Categories.Category" })
.Description = "The categories for the store";
}
诀窍是对include使用点格式,它允许您定义include路径
之所以需要这样做,是因为GraphQL.EntityFramework将应用includeNames参数数组中的所有Include,但它们都应用于源实体级别:Store-不直接支持.ThenClude
Categories.Categories相当于.Includex=>x.Categories.thenCludex=>x.Categories
public StoreType(IEfGraphQLService<MyDbContext> efGraphQlService) : base(efGraphQlService)
{
Field(x => x.StoreId).Description("The store ID");
Field(x => x.Name).Description("The store name");
AddNavigationListField(
name: "categories",
resolve: context => context.Source.Categories.Select(x => x.Category));
}
Field<ListGraphType<CategoryType>>(
name: "categories",
resolve: context =>
{
var dbContext = ResolveDbContext(context);
return dbContext.StoreCategories
.AsNoTracking()
.Include(x => x.Category)
.Where(x => x.StoreId == context.Source.StoreId)
.Select(x => x.Category);
});
public StoreType(IEfGraphQLService<MyDbContext> efGraphQlService) : base(efGraphQlService)
{
Field(x => x.StoreId).Description("The store ID");
Field(x => x.Name).Description("The store name");
// ...
AddNavigationListField(
name: "categories",
resolve: context => context.Source.Categories.Select(x => x.Category),
includeNames: new[] { "Categories.Category" })
.Description = "The categories for the store";
}