在整个应用程序中,许多不同查询中出现的某些标准已经慢慢变得更加复杂。为了避免重复此代码,我想将这些条件拆分为一个方法,该方法将条件作为表达式返回,然后可以在必要时应用:
public Expression<Func<Invoice, bool>> GetComplexPredicate()
{
// complex predicate is returned as an Expression:
return c => ...
}
重复使用:
var result = repository.Invoice.Where(GetComplexPredicate())
但是,下面的声明不会编译,因为 c.Invoice 只是 ICollection 。
var result = repository.Customer
.Where(c => c.Country == "US" && c.Invoice.Any(GetComplexPredicate()))
是否可以使用这样的表达式?
答案 0 :(得分:6)
这个问题分为两部分:
如何在L2E查询中的导航属性上使用谓词表达式?
L2E允许在查询中使用 AsQueryable 扩展方法。这意味着我可以将 ICollection 转换为 IQueryable 并应用谓词表达式。到现在为止还挺好。但是,它可能会编译,但它仍然无法运行,因为L2E将不知道如何处理GetComplexPredicate方法中的预定义表达式。这导致我们:
如何将多个单独的谓词表达式合并为一个?
非常有用的 LINQKit 可以使用PredicateBuilder轻松地将多个谓词组合成一个表达式。使用LINQKit中的 Expand 方法和前面提到的 AsQueryable ,我们终于可以得到一个既能编译又能运行良好的语句:
// build the entire predicate beforehand (PredicateBuilder + AsQueryable):
var complexPredicate = GetComplexPredicate();
var condition = PredicateBuilder.True<Customer>()
.And(c => c.Country == "US")
.And(c => c.Invoice.AsQueryable().Any(complexPredicate));
// apply criteria to query (using Expand):
var result = repository.Customer.Where(condition.Expand()).ToList();