Hot Chocolate自定义字段无法使用过滤及排序功能问题求助
问题原因
Hot Chocolate默认的[UseFiltering]/[UseSorting]特性只会识别查询返回的IQueryable对应实体的原生数据库字段,你当前实现的messageCount是运行时通过字段Resolver单独计算的后置字段,没有出现在初始查询的IQueryable结构中,所以默认生成的过滤输入类型不会包含该字段,自然会抛出字段不存在的报错。
你之前在ConversationType或者messageCount字段上加[UseFiltering]的尝试完全是误用:该位置的UseFiltering是用于控制「messageCount字段自身支持过滤查询」,和「查询Conversation列表时用messageCount作为过滤条件」是完全无关的两个功能。
另外你当前的messageCountResolver实现存在N+1查询问题:每返回1条会话记录就要单独查一次数据库统计消息数,会话数量多的时候性能会非常差。
可行解决方案
方案1:投影预计算(最推荐,性能最优)
直接在会话查询接口中把messageCount作为IQueryable的一部分预计算,不需要额外的Resolver,Hot Chocolate会自动识别该字段支持过滤排序,且会翻译成原生SQL执行,无N+1问题。
- 定义会话DTO(也可以用匿名类型,推荐显式定义DTO):
public class ConversationDto { // 复制Conversation实体所有原生字段 public int Id { get; set; } // 其他原生字段... // 新增消息数字段 public int MessageCount { get; set; } }
- 修改会话查询接口实现:
[ExtendObjectType(OperationTypeNames.Query)] public class ConversationQueries { [UseOurDbContext] [UsePaging(IncludeTotalCount = true)] [UseFiltering] [UseSorting] public IQueryable<ConversationDto> GetConversationsAsync([ScopedService] OurDbContext dbContext) { return dbContext.Conversations.Select(c => new ConversationDto { // 赋值所有原生字段 Id = c.Id, // 其他字段... // 预计算消息数,会被EF Core翻译成SQL的COUNT(*) MessageCount = c.Messages.Count() }); } }
- 把之前定义的
messageCount字段Resolver删除即可,该方案下过滤、排序、查询都可以直接正常使用。
方案2:扩展过滤输入类型(无侵入,不改现有结构)
如果你不想修改现有实体和Resolver结构,可以通过扩展过滤输入类型+绑定表达式的方式实现:
- 自定义会话过滤输入类型,新增
messageCount字段:
public class ConversationFilterInputType : FilterInputType<Model.Conversation> { protected override void Configure(IFilterInputTypeDescriptor<Model.Conversation> descriptor) { // 新增messageCount过滤字段,绑定对应的统计表达式 descriptor.Field("messageCount") .Type<IntOperationFilterInputType>() .Filter(c => c.Messages.Count()); } }
- 修改查询接口的过滤特性,指定自定义的过滤输入类型:
[UseFiltering(typeof(ConversationFilterInputType))] [UseSorting] public async Task<IEnumerable<Model.Conversation>> GetConversationsAsync([ScopedService] OurDbContext dbContext) { return dbContext.Conversations.ToListAsync(); }
该方案不需要修改现有Resolver逻辑,配置完成后即可支持messageCount的过滤操作,排序如果需要支持可以用同样的方式扩展排序输入类型。
内容的提问来源于stack exchange,提问作者Willy K.
相关产品推荐
相关产品推荐

