使用foreach循环构建自定义谓词以充当过滤器

5 c# linq-to-entities expression-trees linq-expressions linqkit

我需要通过将文档列表传递给我正在努力使用循环动态构建的自定义过滤器来过滤文档列表foreach:

var mainPredicate = PredicateBuilder.True<Document>();

// mainPredicate is combined to other filters successfully here ...

var innerPredicate = PredicateBuilder.False<Document>();
foreach (var period in periods)
{
    var p = period;
    Expression<Func<Document, bool>> inPeriod =
        d => d.Date >= p.DateFrom && d.Date <= p.DateTo;

    innerPredicate = innerPredicate.Or(d => inPeriod.Invoke(d));
}

mainPredicate = mainPredicate.And(innerPredicate);
Run Code Online (Sandbox Code Playgroud)

最后一行:

documents = this.ObjectSet.AsExpandable().Where(mainPredicate).ToList();
Run Code Online (Sandbox Code Playgroud)

引发此异常:

参数"d"未绑定在指定的LINQ to Entities查询表达式中.

任何人都知道为什么我得到这个例外?我不明白我传递给InPeriod方法的'd'参数丢失了.我不知道为什么缺少这个工作.我的代码与许多其他完美运行的示例相同.任何关于调用表达式的理论理论信息及其在幕后的工作方式都是值得欢迎的.

小智 1

最后,我找到了一种方法来避免将多个谓词组合到主表达式树中。

鉴于每个谓词代表一个不同的过滤器,并且我希望最终的组合过滤器成为一系列必须遵守的条件,我们可以说每个谓词都必须返回true,最终谓词才能返回 true。

为了使其发挥作用,谓词必须与 结合使用AND。因此,生成的 SQL 查询必须如下所示:

predicate1 AND predicate2 AND predicate3...

组合这些谓词的更好方法AND是将Where查询运算符链接到最终查询,如下所示:

var documents = this.ObjectSet.AsExpandable()
    .Where(mainPredicate)
    .Where(otherPredicate)
    .Where(yetAnotherPredicate)
    .ToList();
Run Code Online (Sandbox Code Playgroud)

生成的 SQL 查询会将这些谓词中的每一个与 组合起来AND。这正是我想做的。

这比我自己破解表达式树更容易。