EF Core "InvalidOperationException: Include has been used on non entity queryable" for navigation property even after explicit include

c# dynamic-linq entity-framework graphql linq

Question

I've created a sample project which uses the following packages -

  1. GraphQL
  2. GraphQL.EntityFramework
  3. System.Linq.Dynamic.Core

The idea here is to translate the selection done in the GraphQL query and pass that onto EntityFramework in order not to over-fetch columns that are not asked for in the query. For this I'm passing the Select expression in the form on a string using System.Linq.Dynamic.Core. I've seen that there is an issue on the EntityFramework github repo for fetching navigation properties which states that include is a must, as discussed here. Following that I've included the navigation properties needed before making the Select but for some reason it complains with the following error -

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)

and here is the piece of code that is failing

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;
        }
    }
}

when I issue the following GraphQL query

query {
  customers {
    customerName
    orders {
      orderID
      orderDate
    }
  }
}

The full code example is hosted on github instead of pasting it here as it will be too long to read. Any help would be highly appreciated.

1
1
1/7/2020 7:01:13 PM

Popular Answer

Did you try this project : https://github.com/StefH/GraphQL.EntityFrameworkCore.DynamicLinq ?

With this project you can easily expose all properties from the EF Entities as searchable fields on the GraphQL query.

For example, see https://github.com/StefH/GraphQL.EntityFrameworkCore.DynamicLinq/tree/master/examples/MyHotel

0
1/9/2020 6:04:42 PM


Related Questions





Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow