如何在entity framework对象的LINQ to Entities中使用谓词
我在我的数据访问层中使用LINQ to Entities for Entity Framework对象。
我的目标是尽可能多地从数据库中过滤,而不将过滤逻辑应用于内存中的结果。
为此,业务逻辑层将谓词传递给数据访问层。
我的意思是
Func
所以,如果我直接使用这个谓词,就像
public IQueryable GetAllMatchedEntities(Func isMatched) { return qry = _Context.MyEntities.Where(x => isMatched(x)); }
我得到了例外
[System.NotSupportedException] — {“LINQ to Entities中不支持LINQ表达式节点类型’Invoke’。”}
该问题的解决方案建议使用LINQKit库中的AsExpandable()方法。
但是,再次使用
public IQueryable GetAllMatchedEntities(Func isMatched) { return qry = _Context.MyEntities.AsExpandable().Where(x => isMatched(x)); }
我得到了例外
无法将类型为“System.Linq.Expressions.FieldExpression”的对象强制转换为“System.Linq.Expressions.LambdaExpression”
是否有方法在LINQ to Entities查询entity framework对象中使用谓词,以便将其正确转换为SQL语句。
谢谢。
你不需要LinqKit来做这件事。 只记得使用
Expression>
代替
Func
像这样的东西:
public IQueryable GetAllMatchedEntities(Expression> predicate) { return _Context.MyEntities.Where(predicate); }
您必须使用Expression,因为Linq to Entities需要将您的lambda转换为SQL。
当你使用Func时,你的lambda被编译为IL,但是当使用Expression时,它是Linq to Entities可以横向和转换的表达式树。
这适用于Linq to Entities理解的表达式。
如果它一直失败,那么你的表达式会执行Linq to Entities无法转换为SQL的内容。 在那种情况下,我不认为LinqKit会有所帮助。
编辑:
无需转换。 只需使用Expression参数定义GetAllMatchedEntities方法,并以与Func参数相同的方式使用它。 编译器完成剩下的工作。
有三种方法可以使用GetAllMatchedEntities。
1)使用内联lambda表达式:
this.GetAllMatchedEntities(x => x.Age > 18)
2)将表达式定义为字段(也可以是变量)
private readonly Expression> IsMatch = x => x.Age > 18; ...then use it this.GetAllMatchedEntities(IsMatch)
3)您可以手动创建表达式。 缩小尺寸是更多的代码,你错过了编译时检查。
public Expression> IsMatchedExpression() { var parameterExpression = Expression.Parameter(typeof (MyEntity)); var propertyOrField = Expression.PropertyOrField(parameterExpression, "Age"); var binaryExpression = Expression.GreaterThan(propertyOrField, Expression.Constant(18)); return Expression.Lambda>(binaryExpression, parameterExpression); }
Linq to Entities中使用的方法必须由Linq提供程序进行规范映射才能工作。 由于Linq提供程序(在您的情况下为EF)无法将谓词映射到内部方法,因此会引发错误。
对于LINQ场景,针对entity framework的查询涉及通过规范函数将某些CLR方法映射到基础数据源上的方法。 LINQ to Entities查询中未显式映射到规范函数的任何方法调用都将导致抛出运行时NotSupportedExceptionexception
来源:规范函数映射的CLR方法( http://msdn.microsoft.com/en-us/library/bb738681.aspx )
您可以尝试使用ARE映射的方法并将它们链接到Linq表达式,或使用存储过程。 但是在EF支持所有CLR之前,你将不得不找到解决办法。
从好的方面来看,每个版本似乎都会在规范列表中添加更多内容。
值得一读的解决方案: http : //msdn.microsoft.com/en-us/library/dd456857.aspx