通用 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()
您的 shortFunction
是 Func<>
而不是 Expression
,因此无法转换为 SQL。尝试改成 Expression<Func<>>
类型。
C# 编译器具有将 lambda 转换为两种类型的特殊逻辑 - 如果所需的结果类型为 Func<>
,则将其转换为编译代码,如果结果类型为 Expression
,则将其转换为它到代表代码的 Expression
树(为 LINQ 添加的欺骗)。数据提供者可以读取该表达式树并为相关数据库发出代码(例如 SQL),但它无法将已编译的 IL 代码反编译回可以用另一种语言输出的内容。
我正在尝试通过助手 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()
您的 shortFunction
是 Func<>
而不是 Expression
,因此无法转换为 SQL。尝试改成 Expression<Func<>>
类型。
C# 编译器具有将 lambda 转换为两种类型的特殊逻辑 - 如果所需的结果类型为 Func<>
,则将其转换为编译代码,如果结果类型为 Expression
,则将其转换为它到代表代码的 Expression
树(为 LINQ 添加的欺骗)。数据提供者可以读取该表达式树并为相关数据库发出代码(例如 SQL),但它无法将已编译的 IL 代码反编译回可以用另一种语言输出的内容。