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

Generic Linq query NotSupportedException: Could not parse expression

我正在尝试通过助手 class 在 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();

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

where DTO : BaseRevisionDTO
where Domain : BaseTrackedObject
where DomainRevision : BaseRevision

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

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

编辑 1:

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

        GetStateAsRevision(GetDomainSearchExpression(GetDomainSearchFunction()));

它将在以下位置出错:

        List<Domain> oriList = oriSet.Where(query).ToList();

这是整个堆栈跟踪:

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()

您的 shortFunctionFunc<> 而不是 Expression,因此无法转换为 SQL。尝试改成 Expression<Func<>> 类型。

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