EF Core "InvalidOperationException: include был использован для незапрашиваемых объектов" для свойства навигации даже после явного включения - PullRequest
1 голос
/ 07 января 2020

Я создал пример проекта, который использует следующие пакеты -

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

Идея состоит в том, чтобы перевести выбор, выполненный в запросе GraphQL, и передать его в EntityFramework, чтобы не перебирать столбцы, которые не запрашиваются в запросе. Для этого я передаю выражение Select в форме строки, используя System.Linq.Dynamic.Core. Я видел, что существует проблема в репозитории EntityFramework github для получения навигационных свойств, для которых необходимо указать состояния, как обсуждено здесь . После этого я включил необходимые свойства навигации перед созданием 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 Ответ

0 голосов
/ 09 января 2020

Вы пробовали этот проект: https://github.com/StefH/GraphQL.EntityFrameworkCore.DynamicLinq?

В этом проекте вы можете легко представить все свойства объектов EF в качестве полей для поиска в запросе GraphQL.

Например, см. https://github.com/StefH/GraphQL.EntityFrameworkCore.DynamicLinq/tree/master/examples/MyHotel

...