即使在显式包含之后,EF Core“InvalidOperationException:包含已用于非实体可查询”的导航属性也是如此

Posted

技术标签:

【中文标题】即使在显式包含之后,EF Core“InvalidOperationException:包含已用于非实体可查询”的导航属性也是如此【英文标题】:EF Core "InvalidOperationException: Include has been used on non entity queryable" for navigation property even after explicit include 【发布时间】:2020-04-25 07:42:42 【问题描述】:

我创建了一个使用以下包的示例项目 -

    GraphQL GraphQL.EntityFramework System.Linq.Dynamic.Core

这里的想法是翻译在 GraphQL 查询中完成的选择并将其传递给 EntityFramework,以免过度获取查询中未要求的列。为此,我使用System.Linq.Dynamic.Core 以字符串形式传递Select 表达式。我已经看到 EntityFramework github repo 上存在一个问题,用于获取导航属性,其中包含是必须的,正如 here 所讨论的那样。之后,我在制作 Select 之前包含了所需的导航属性,但由于某种原因它抱怨以下错误 -

GraphQL.ExecutionError: Error trying to resolve customers.
---> System.InvalidOperationException: Include has been used on non entity queryable.
at Microsoft.EntityFrameworkCore.Query.Internal.NavigationExpandingExpressionVisitor.ProcessInclude(NavigationExpansionExpression source, Expression expression, Boolean thenInclude)
at Microsoft.EntityFrameworkCore.Query.Internal.NavigationExpandingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
at System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor visitor)
at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
at Microsoft.EntityFrameworkCore.Query.Internal.NavigationExpandingExpressionVisitor.Expand(Expression query)
at Microsoft.EntityFrameworkCore.Query.QueryTranslationPreprocessor.Process(Expression query)
at Microsoft.EntityFrameworkCore.Query.QueryCompilationContext.CreateQueryExecutor[TResult](Expression query)
at Microsoft.EntityFrameworkCore.Storage.Database.CompileQuery[TResult](Expression query, Boolean async)
at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.CompileQueryCore[TResult](IDatabase database, Expression query, IModel model, Boolean async)
at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.<>c__DisplayClass12_0`1.<ExecuteAsync>b__0()
at Microsoft.EntityFrameworkCore.Query.Internal.CompiledQueryCache.GetOrAddQueryCore[TFunc](Object cacheKey, Func`1 compiler)
at Microsoft.EntityFrameworkCore.Query.Internal.CompiledQueryCache.GetOrAddQuery[TResult](Object cacheKey, Func`1 compiler)
at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.ExecuteAsync[TResult](Expression query, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryProvider.ExecuteAsync[TResult](Expression expression, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable`1.GetAsyncEnumerator(CancellationToken cancellationToken)
at System.Runtime.CompilerServices.ConfiguredCancelableAsyncEnumerable`1.GetAsyncEnumerator()
at Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.ToListAsync[TSource](IQueryable`1 source, CancellationToken cancellationToken)
at GraphQL.EntityFramework.EfGraphQLService`1.<>c__DisplayClass26_0`2.<<BuildQueryField>b__0>d.MoveNext() in C:\\projects\\graphql-entityframework\\src\\GraphQL.EntityFramework\\GraphApi\\EfGraphQLService_Queryable.cs:line 130
at GraphQL.Instrumentation.MiddlewareResolver.Resolve(ResolveFieldContext context)
at GraphQL.Execution.ExecutionStrategy.ExecuteNodeAsync(ExecutionContext context, ExecutionNode node)

这是失败的代码

public class QueryTest : QueryGraphType<TestDBContext>

    public QueryTest(IEfGraphQLService<TestDBContext> graphQlService) :
        base(graphQlService)
    
        Name = "Query";
        AddQueryField(
            name: "customers",
            // the next line is failing
            resolve: context => context.DbContext.Customers.Include(x => x.Orders).Select<Customer>(GetSelect(context.SubFields))                
        );
        AddQueryField(
            name: "orders",
            resolve: context => context.DbContext.Orders.Include(x => x.Customer).Select<Order>(GetSelect(context.SubFields))
        );
    

    private string GetSelect(IDictionary<string, Field> subfields) => $"new(string.Join(",", GetSelectedColumns(subfields)))";

    private IEnumerable<string> GetSelectedColumns(IDictionary<string, Field> subfields)
    
        foreach (var item in subfields)
        
            if (item.Value.SelectionSet.Children.Count() > 0)
            
                continue;
            
            yield return item.Key;
        
    

当我发出以下 GraphQL 查询时

query 
  customers 
    customerName
    orders 
      orderID
      orderDate
    
  

完整的代码示例托管在github 上,而不是在这里粘贴,因为它太长了无法阅读。任何帮助将不胜感激。

【问题讨论】:

【参考方案1】:

您是否尝试过这个项目:https://github.com/StefH/GraphQL.EntityFrameworkCore.DynamicLinq?

使用此项目,您可以轻松地将 EF 实体中的所有属性公开为 GraphQL 查询中的可搜索字段。

例如,见https://github.com/StefH/GraphQL.EntityFrameworkCore.DynamicLinq/tree/master/examples/MyHotel

【讨论】:

我今天会尝试一下,让你知道结果如何。 不幸的是,GraphQL.EntityFrameworkCore.DynamicLinq 库并没有完全解决我的问题。我已经打开了一个 Github 问题。

以上是关于即使在显式包含之后,EF Core“InvalidOperationException:包含已用于非实体可查询”的导航属性也是如此的主要内容,如果未能解决你的问题,请参考以下文章

Prisma:在显式多对多关系中创建或连接记录

postgres 自动增量未在显式 id 插入时更新

EF Core - 为啥显式加载非常慢?

Unity:在显式导航中使用自动导航

.NET Core EF框架使用SQL server 2008数据库分页问题:Incorrect syntax near 'OFFSET'. Invalid usage of the

Matlab保存忽略大单元格数组