Hot Chocolate如何跨表投影属性,在Schema不同层级暴露字段
跨关联表隐藏层级的Hot Chocolate投影配置方案
你之前触发
A composite type always needs to specify a selection set报错的根因是:IsProjected(true)作用于Bar这个复合类型字段时,Hot Chocolate无法感知该关联表需要投影的具体字段,而你又没有在GraphQL查询中请求Bar的子字段,因此投影逻辑无法生成合法的SQL语句。
以下是适配你场景(Hot Chocolate v11 + EF Core + 单次查询 + 不暴露Bar层级)的两种可行方案:
方案一:自定义字段直接绑定关联表投影(推荐,无需修改实体类)
直接在FooType.cs中配置自定义Baz字段的投影表达式,让Hot Chocolate的UseProjection中间件直接识别该字段对应底层Foo.Bar.Baz的关联属性,自动生成连表查询逻辑:
public class FooType : ObjectType<Foo> { protected override void Configure(IObjectTypeDescriptor<Foo> descriptor) { // 隐藏原有的Bar字段,不暴露给API客户端 descriptor.Ignore(f => f.Bar); // 配置对外暴露的Baz字段 descriptor .Field("Baz") // 替换为Baz属性的实际GraphQL类型,比如IntType/StringType等 .Type<StringType>() // 配置投影映射,直接指向关联表的对应属性 .Project(f => f.Bar.Baz) // 配置解析逻辑,实体已加载关联数据时直接取值 .Resolve(ctx => ctx.Parent<Foo>().Bar?.Baz); } }
该方案下UseProjection会自动将Bar.Baz加入EF Core的查询投影,生成的SQL会左连接Bar表拉取对应字段,全程单次查询,无N+1问题,也不需要修改查询逻辑。
方案二:实体层添加映射属性(适合多场景复用)
如果你需要在多处用到Foo.Baz的逻辑,可以在EF实体层添加非映射属性,再配套投影配置:
- 首先修改
Foo实体类:
public class Foo { // 原有属性保留 public int Id { get; set; } public Bar Bar { get; set; } // 添加非映射的Baz属性 [NotMapped] public string Baz => Bar?.Baz; }
- 再在
FooType.cs中配置投影即可:
public class FooType : ObjectType<Foo> { protected override void Configure(IObjectTypeDescriptor<Foo> descriptor) { descriptor.Ignore(f => f.Bar); // 直接绑定实体的Baz属性,配置投影映射 descriptor.Field(f => f.Baz).Project(f => f.Bar.Baz); } }
两种方案都可以满足你隐藏Bar层级、单次查询完成、不污染查询逻辑的需求,兼容Hot Chocolate v11和.NET Core 3.1版本。
内容的提问来源于stack exchange,提问作者Braden Cok
相关产品推荐
相关产品推荐

