IQueryable ToListAsync在使用自定义结构时抱怨违反约束

时间:2019-07-05 13:53:53

标签: c# .net entity-framework linq ef-core-2.2

上下文

我正在尝试编写一个将IQueryable<T>转换为IQueryable<CustomType<T, K>>的函数,然后可以在以后根据需要将其转换为IEnumerable<CustomType<T, K>>

问题

给出:

public struct CustomType<TModel, TKey>
{
    public TKey Key { get; set; }
    public TModel Value { get; set; }
}

如果我写:

var list = await query
    .Select(selectExpression) // Selects into `CustomType<T, K>`
    .Where(whereExpression)
    .OrderBy(orderByExpression)
    .Select(x => new { Value = x.Value })
    .ToListAsync();

其中selectExpression是运行时构建的表达式,等效于:

x => new CustomType<T, K> { Key = ..., Value = ... }

然后一切都按预期工作,并将在运行时构建的selectExpression转换为单个SQL表达式。

但是,如果我在任何时候返回CustomType<T, K>,例如:

var list = await query
    .Select(selectExpression) // Selects into `CustomType<T, K>`
    .ToListAsync();

然后EF Core抱怨在某些实体跟踪功能CustomType<T, K>中违反了一些约束TIn(为什么要尝试跟踪自定义类型?)

特定的错误代码是此代码(对于CustomType<OtherType, int>):

GraphQL.ExecutionError: GenericArguments[1], 'CustomType`2[OtherType,System.Int32]', on 'System.Collections.Generic.IAsyncEnumerable`1[TOut] _TrackEntities[TOut,TIn](System.Collections.Generic.IAsyncEnumerable`1[TOut], Microsoft.EntityFrameworkCore.Query.QueryContext, System.Collections.Generic.IList`1[Microsoft.EntityFrameworkCore.Query.Internal.EntityTrackingInfo], System.Collections.Generic.IList`1[System.Func`2[TIn,System.Object]])' violates the constraint of type 'TIn'. ---> GraphQL.Conventions.Execution.FieldResolutionException: GenericArguments[1], 'CustomType`2[OtherType,System.Int32]', on 'System.Collections.Generic.IAsyncEnumerable`1[TOut] _TrackEntities[TOut,TIn](System.Collections.Generic.IAsyncEnumerable`1[TOut], Microsoft.EntityFrameworkCore.Query.QueryContext, System.Collections.Generic.IList`1[Microsoft.EntityFrameworkCore.Query.Internal.EntityTrackingInfo], System.Collections.Generic.IList`1[System.Func`2[TIn,System.Object]])' violates the constraint of type 'TIn'. ---> System.ArgumentException: GenericArguments[1], 'Persistence.IQueryableExtensions+OrderedGroupItem`2[OtherType,System.Int32]', on 'System.Collections.Generic.IAsyncEnumerable`1[TOut] _TrackEntities[TOut,TIn](System.Collections.Generic.IAsyncEnumerable`1[TOut], Microsoft.EntityFrameworkCore.Query.QueryContext, System.Collections.Generic.IList`1[Microsoft.EntityFrameworkCore.Query.Internal.EntityTrackingInfo], System.Collections.Generic.IList`1[System.Func`2[TIn,System.Object]])' violates the constraint of type 'TIn'. ---> System.Security.VerificationException: Method Microsoft.EntityFrameworkCore.Query.Internal.AsyncLinqOperatorProvider._TrackEntities: type argument 'Persistence.IQueryableExtensions+OrderedGroupItem`2[OtherType,System.Int32]' violates the constraint of type parameter 'TIn'.
   at System.RuntimeMethodHandle.GetStubIfNeeded(RuntimeMethodHandleInternal method, RuntimeType declaringType, RuntimeType[] methodInstantiation)
   at System.Reflection.RuntimeMethodInfo.MakeGenericMethod(Type[] methodInstantiation)
   --- End of inner exception stack trace ---
   at System.RuntimeType.ValidateGenericArguments(MemberInfo definition, RuntimeType[] genericArguments, Exception e)
   at System.Reflection.RuntimeMethodInfo.MakeGenericMethod(Type[] methodInstantiation)
   at Microsoft.EntityFrameworkCore.Query.EntityQueryModelVisitor.TrackEntitiesInResults[TResult](QueryModel queryModel)
   at Microsoft.EntityFrameworkCore.Query.EntityQueryModelVisitor.CreateAsyncQueryExecutor[TResult](QueryModel queryModel)
   at Microsoft.EntityFrameworkCore.Query.Internal.CompiledQueryCache.GetOrAddQueryCore[TFunc](Object cacheKey, Func`1 compiler)
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.ExecuteAsync[TResult](Expression query)
   at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable`1.System.Collections.Generic.IAsyncEnumerable<TResult>.GetEnumerator()
   at System.Linq.AsyncEnumerable.Aggregate_[TSource,TAccumulate,TResult](IAsyncEnumerable`1 source, TAccumulate seed, Func`3 accumulator, Func`2 resultSelector, CancellationToken cancellationToken) in D:\a\1\s\Ix.NET\Source\System.Interactive.Async\Aggregate.cs:line 118

如何使它工作,以便ToListAsync在使LINQ to SQL工作(意味着构建一个SQL表达式)的同时返回CustomType<T, K>

我尝试了什么

我尝试将CustomType设为class,但是由于某种原因,由于自定义,LINQ to SQL无法为selectExpression生成单个SQL表达式类型为class

0 个答案:

没有答案