通用 Linq 查询 NotSupportedException:无法解析表达式

Smi*_*thy 2 c# generics linq-to-entities entity-framework

我试图通过一个帮助类来过滤 Entity Framework 核心中的一些结果,但我收到了这个错误,我不知道为什么:

NotSupportedException: Could not parse expression 'value(Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable'1[eVendCustomerDAL.DomainModels.Bin]).Any(__funcTest_0)': The given arguments did not match the expected arguments: Object of type 'System.Linq.Expressions.TypedParameterExpression' cannot be converted to type 'System.Linq.Expressions.LambdaExpression'.

这就是发生错误的地方:

    public virtual Revision<DTO> GetStateAsRevision(
        Expression<Func<Domain, bool>> query) {
        //get all the stateful data from the database
        DbSet<Domain> oriSet = db.Set<Domain>();
        //query all the data
        List<Domain> oriList = oriSet.Where(query).ToList();
Run Code Online (Sandbox Code Playgroud)

该错误似乎是由于query我正在推送的参数而发生的,并且它仅在运行时发生。我不确定是否应该归咎于它的通用性。泛型也是类而不是接口。

where DTO : BaseRevisionDTO
where Domain : BaseTrackedObject
where DomainRevision : BaseRevision
Run Code Online (Sandbox Code Playgroud)

然后我使用以下片段构建表达式:

    private Expression<Func<Domain, bool>> GetDomainSearchExpression(Func<Domain, bool> shortFunction) {
        DbSet<Domain> modelTable = CustomerContext.Set<Domain>();

        Expression<Func<Domain, bool>> expr =
        d =>
        modelTable.Any(shortFunction);

        return expr;
    }

    protected override Func<DomainModels.Bin, bool> GetDomainSearchFunction() {
        return x => x.Station.Machine.UniqueId == MachineID;
    }
Run Code Online (Sandbox Code Playgroud)

编辑1:

所以如果我像这样调用上面的代码:

        GetStateAsRevision(GetDomainSearchExpression(GetDomainSearchFunction()));
Run Code Online (Sandbox Code Playgroud)

它会在以下位置出错:

        List<Domain> oriList = oriSet.Where(query).ToList();
Run Code Online (Sandbox Code Playgroud)

这是整个堆栈跟踪:

NotSupportedException: Could not parse expression 'value(Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable`1[eVendCustomerDAL.DomainModels.Bin]).Any(__shortFunction_0)': The given arguments did not match the expected arguments: Object of type 'System.Linq.Expressions.TypedParameterExpression' cannot be converted to type 'System.Linq.Expressions.LambdaExpression'.
Remotion.Linq.Parsing.Structure.MethodCallExpressionParser.CreateExpressionNode(Type nodeType, MethodCallExpressionParseInfo parseInfo, Object[] additionalConstructorParameters)
Remotion.Linq.Parsing.Structure.MethodCallExpressionParser.Parse(string associatedIdentifier, IExpressionNode source, IEnumerable<Expression> arguments, MethodCallExpression expressionToParse)
Remotion.Linq.Parsing.Structure.ExpressionTreeParser.ParseMethodCallExpression(MethodCallExpression methodCallExpression, string associatedIdentifier)
Remotion.Linq.Parsing.Structure.ExpressionTreeParser.ParseTree(Expression expressionTree)
Remotion.Linq.Parsing.Structure.QueryParser.GetParsedQuery(Expression expressionTreeRoot)
Remotion.Linq.Parsing.ExpressionVisitors.SubQueryFindingExpressionVisitor.Visit(Expression expression)
System.Linq.Expressions.ExpressionVisitor.VisitLambda<T>(Expression<T> node)
System.Linq.Expressions.Expression.Accept(ExpressionVisitor visitor)
Remotion.Linq.Parsing.ExpressionVisitors.SubQueryFindingExpressionVisitor.Visit(Expression expression)
System.Linq.Enumerable+SelectListPartitionIterator.ToArray()
System.Linq.Enumerable.ToArray<TSource>(IEnumerable<TSource> source)
Remotion.Linq.Parsing.Structure.MethodCallExpressionParser.Parse(string associatedIdentifier, IExpressionNode source, IEnumerable<Expression> arguments, MethodCallExpression expressionToParse)
Remotion.Linq.Parsing.Structure.ExpressionTreeParser.ParseMethodCallExpression(MethodCallExpression methodCallExpression, string associatedIdentifier)
Remotion.Linq.Parsing.Structure.ExpressionTreeParser.ParseTree(Expression expressionTree)
Remotion.Linq.Parsing.Structure.QueryParser.GetParsedQuery(Expression expressionTreeRoot)
Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.CompileQueryCore<TResult>(Expression query, INodeTypeProvider nodeTypeProvider, IDatabase database, ILogger logger, Type contextType)
Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler+<>c__DisplayClass19_0.<CompileQuery>b__0()
Microsoft.EntityFrameworkCore.Query.Internal.CompiledQueryCache.GetOrAddQueryCore<TFunc>(object cacheKey, Func<Func<QueryContext, TFunc>> compiler)
Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.Execute<TResult>(Expression query)
Remotion.Linq.QueryableBase.GetEnumerator()
System.Collections.Generic.List..ctor(IEnumerable<T> collection)
System.Linq.Enumerable.ToList<TSource>(IEnumerable<TSource> source)
eVendWebAPI.Helpers.DALHelpers.GetRevisionHelper.GetStateAsRevision(Expression<Func<DomainModel, bool>> query) in GetRevisionHelper.cs
+
            List<DomainModel> oriList = oriSet.Where(query).ToList();
eVendWebAPI.Helpers.DALHelpers.GetRevisionHelper.GetRevision(Expression<Func<DomainModel, bool>> query) in GetRevisionHelper.cs
+
            return GetStateAsRevision(query);
eVendWebAPI.Areas.Customer.Controllers.Base.BaseAPIRevisionController.Get() in BaseAPIRevisionController.cs
+
            return Ok(helper.GetRevision(searchExpr));
lambda_method(Closure , object , Object[] )
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker+<InvokeActionMethodAsync>d__27.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker+<InvokeNextActionFilterAsync>d__25.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Rethrow(ActionExecutedContext context)
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted)
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker+<InvokeNextResourceFilter>d__22.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Rethrow(ResourceExecutedContext context)
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted)
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker+<InvokeAsync>d__20.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
Microsoft.AspNetCore.Builder.RouterMiddleware+<Invoke>d__4.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
Microsoft.AspNetCore.Builder.RouterMiddleware+<Invoke>d__4.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
Microsoft.AspNetCore.Authentication.AuthenticationMiddleware+<Invoke>d__18.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
Microsoft.AspNetCore.Authentication.AuthenticationMiddleware+<Invoke>d__18.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
Microsoft.VisualStudio.Web.BrowserLink.BrowserLinkMiddleware+<ExecuteWithFilter>d__7.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware+<Invoke>d__7.MoveNext()
Run Code Online (Sandbox Code Playgroud)

Net*_*age 6

shortFunction是 aFunc<>而不是 anExpression所以它不能转换为 SQL。尝试使其成为类型Expression<Func<>>

C# 编译器具有将 lambda 转换为两种类型的特殊逻辑 -​​ 如果所需的结果类型是,Func<>则将其转换为编译代码,如果结果类型是Expression,则将其转换为Expression表示代码的树(为 LINQ 添加的作弊) . 数据提供者可以读取该表达式树并为相关数据库(例如 SQL)发出代码,但它无法将编译后的 IL 代码反编译回可以用另一种语言输出的内容。