我正在尝试在我的EF过滤代码中使用谓词。
这有效:
IQueryable<Customer> filtered = customers.Where(x => x.HasMoney && x.WantsProduct);
但是这个:
Predicate<T> hasMoney = x => x.HasMoney;
Predicate<T> wantsProduct = x => x.WantsProduct;
IQueryable<Customer> filtered = customers.Where(x => hasMoney(x) && wantsProduct(x));
在运行时失败:
The LINQ expression node type 'Invoke' is not supported in LINQ to Entities.
我不能使用第一个选项,因为这是一个简单的例子,实际上,我正在尝试将一堆谓词组合在一起(使用and,not,或等)来实现我想要的
如何让EF Linq提供商“理解”我的谓词?
如果我使用Func<T, bool>
,我会得到相同的结果。它适用于Expression<Func<T>>
,但我无法将表达式组合在一起进行复杂过滤。如果可能的话,我宁愿避免使用外部库。
更新:
如果无法做到这一点,我有什么选择?也许表达方式可以某种方式结合/或“和/”以达到同样的效果?
答案 0 :(得分:10)
Expression<Func<Customer, bool>> hasMoney = x => x.HasMoney;
Expression<Func<Customer, bool>> wantsProduct = x => x.WantsProduct;
IQueryable<Customer> filtered = customers.Where(hasMoney).Where(wantsProduct);
Expression<T>
将x => x.HasMoney
保留为表达式树,而不是将其编译为.NET方法Expression<Func<Customer, bool>>
而不是Expression<Predicate<Customer>>
,因为这是Queryable.Where
所期望的.Where
中传递,使用多个.Where
来电,而不是&&
将它们合并。通过使用.Union
,.Except
等重写条件,可以获得更复杂的条件(包括没有等等)。
另一种方法是使用LINQKit的AsExpandable
:
Expression<Func<Customer, bool>> hasMoney = x => x.HasMoney;
Expression<Func<Customer, bool>> wantsProduct = x => x.WantsProduct;
IQueryable<Customer> filtered = customers.AsExpandable().Where(x => hasMoney.Invoke(x) && wantsProduct.Invoke(x));
答案 1 :(得分:3)
不幸的是,由于无法在SQL查询上映射它,因此无法在EF linq中使用Predicate<T>
。这只能通过表达式来完成,因为它们可以被解析并转换为SQL。
事实上,有4种语言功能使linq成为可能:
更新:
可能的解决方案是以编程方式构建表达式How to: Use Expression Trees to Build Dynamic Queries