在 GraphQL HotChocolate 上过滤 EF 核心导航 属性

Filter EF Core Navigation property on GraphQL HotChocolate

我正在将 HotChocolate (11.2.2) 与 EF Core 一起使用,并希望过滤子 属性。根据 GraphQL 文档,这应该可以通过在导航 属性 上使用 filter 关键字来实现,但是 HotChocolate 只是失败了。

我的架构:

type A {
    Name: string,
    RefTo: [B]
}
type B {
    TypeName: string,
    Value: int
}

这是由 EF 支持的,我向 HotChocolate 提供了一个 IQueryable<A>

    [UsePaging]
    [UseProjection]
    [UseFiltering]
    [UseSorting]
    public IQueryable<A> GetAs([Service] Context db) => db.As.AsSingleQuery().AsNoTrackingWithIdentityResolution();

现在我只想包含 TypeName 等于 "ExampleType" 的那些 B,如下所示:

query {
   As {
      Name,
      RefTo(where: { TypeName: { eq: "ExampleType" } })
      {
          TypeName,
          Value
      }
   }
}

但是 HotChcolate 似乎不理解这一点并说:

Unknown argument "where" on field "A.RefTo".validation

是否可以使用 EF Core 模型过滤导航属性?

您也必须向 RefTo 添加过滤

    [UseFiltering] 
    public ICollection<A> RefTo {get; set;}

如果您想将 UseFilteringUseSorting 等应用于结果类型为 ICollection 的所有字段,您可以使用 TypeInterceptor:

using System;
using System.Collections.Generic;
using HotChocolate.Configuration;
using HotChocolate.Types;
using HotChocolate.Types.Descriptors;
using HotChocolate.Types.Descriptors.Definitions;

namespace MyApp
{
    public class FilterCollectionTypeInterceptor : TypeInterceptor
    {
        private static bool IsCollectionType(Type t)
            => t.IsGenericType && t.GetGenericTypeDefinition() == typeof(ICollection<>);

        public override void OnBeforeRegisterDependencies(ITypeDiscoveryContext discoveryContext, DefinitionBase? definition,
            IDictionary<string, object?> contextData)
        {
            if (definition is not ObjectTypeDefinition objectTypeDefinition) return;
            
            for (var i = 0; i < objectTypeDefinition.Fields.Count; i++)
            {
                var field = objectTypeDefinition.Fields[i];
                if (field.ResultType is null || !IsCollectionType(field.ResultType)) continue;
                
                var descriptor = field.ToDescriptor(discoveryContext.DescriptorContext)
                    .UseFiltering()
                    .UseSorting();
                objectTypeDefinition.Fields[i] = descriptor.ToDefinition();
            }
        }
    }
}

在这里查看我的要点:https://gist.github.com/zliebersbach/b7db2b2fcede98f220f55aa92276ad6e#file-filtercollectiontypeinterceptor-cs