如何在EF Where()子句中使用谓词<t>?</t>

时间:2012-11-15 01:09:31

标签: c# linq entity-framework linq-expressions

我正在尝试在我的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>>,但我无法将表达式组合在一起进行复杂过滤。如果可能的话,我宁愿避免使用外部库。

更新:
如果无法做到这一点,我有什么选择?也许表达方式可以某种方式结合/或“和/”以达到同样的效果?

2 个答案:

答案 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等重写条件,可以获得更复杂的条件(包括没有等等)。

另一种方法是使用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));

答案 1 :(得分:3)

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

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

  1. 扩展方法
  2. 类型推断
  3. 瓶盖
    和linq2sql尤其是
  4. <强>表达式
  5. 更新:
    可能的解决方案是以编程方式构建表达式How to: Use Expression Trees to Build Dynamic Queries