13

我正在尝试在我的 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、or 等)来实现我想要的。

如何让 EF Linq 提供程序“理解”我的谓词?

如果我使用Func<T, bool>. 它适用于Expression<Func<T>>,但我无法将表达式组合在一起进行复杂过滤。如果可能的话,我宁愿避免使用外部库。

更新:
如果无法做到这一点,我有什么选择?也许表达式被组合/或'ed/and'ed以某种方式达到相同的效果?

4

2 回答 2

12
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>离开,而不是将其编译为 .NET 方法x => x.HasMoney
  • 使用Expression<Func<Customer, bool>>而不是Expression<Predicate<Customer>>,因为这是Queryable.Where预期的
  • 直接.Where将其传入 ,使用多个.Where调用而不是&&.

.Union可以通过使用,.Except等重写它们来获得更复杂的条件(包括不,或等) 。

另一种方法是使用LINQKitAsExpandable

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));
于 2012-11-15T08:51:43.027 回答
4

不幸的是,无法Predicate<T>在 EF linq 中使用,因为无法将其映射到 SQL 查询中。这只能通过表达式来完成,因为它们可以被解析并转换为 SQL。

事实上,有 4 种语言特性使 linq 成为可能:

  1. 扩展方法
  2. 类型推断
  3. 闭包
    ,尤其是对于 linq2sql
  4. 表达式

更新:
可能的解决方案是以编程方式构建表达式。如何:使用表达式树构建动态查询

于 2012-11-15T01:20:56.617 回答