由于您正在使用 LINQ,我想您正在使用 LINQ-to-SQL 数据上下文,对吧?我没有备用的 DataContext 来测试这个,但这应该会给你一些想法。
我不知道它是否适用于数据上下文,但其中大多数都是非常基本的东西(链接 OR 运算符和包含方法调用),因此当查询转换为 SQL 时它不应该引起问题。
首先,我创建一个自定义函数来构建我的谓词:
Func<string, Func<DataItem, bool>> buildKeywordPredicate =
keyword =>
x => x.Title.Contains(keyword)
|| x.Contents.Contains(keyword);
这是一个函数,它接受一个字符串关键字,然后返回另一个函数,该函数接受一个 DataItem 并根据关键字检查它。
基本上,如果你传入“Stack”,你会得到一个谓词:x => x.Title.Contains("Stack") || x.Contents.Contains("Stack")
.
接下来,由于有许多可能的关键字,并且您需要使用 OR 操作将其链接起来,因此我创建了另一个辅助函数来将 2 个谓词与 OR 链接在一起
Func<Func<DataItem,bool>, Func<DataItem, bool>, Func<DataItem, bool>> buildOrPredicate =
(pred1, pred2) =>
x => pred1(x) || pred2(x);
此函数接受 2 个谓词,然后用 OR 操作将它们连接起来。
有了这两个函数,我就可以像这样构建我的 where 谓词:
foreach (var word in keywords) {
filter = filter == null
? buildKeywordPredicate(word)
: buildOrPredicate(filter, buildKeywordPredicate(word));
}
循环内的第一行基本上检查过滤器是否为空。如果是,那么我们需要为我们构建一个简单的关键字过滤器。
否则,如果过滤器不为空,我们需要使用 OR 操作链接现有过滤器,因此我们将现有过滤器和新关键字过滤器传递给 buildOrPredicate 来做到这一点。
然后我们现在可以创建查询的 WHERE 部分:
var result = data.Where(filter);
传入我们刚刚构建的复杂谓词。
我不知道这是否与使用 PredicateBuilder 不同,但由于我们将查询转换推迟到 LINQ-to-SQL 引擎,所以应该没有任何问题。
但正如我所说,我还没有针对真实的数据上下文对其进行测试,所以如果有任何问题,您可以在评论中写下。
这是我为测试而构建的控制台应用程序:http: //pastebin.com/feb8cc1e
希望这可以帮助!
编辑:对于涉及正确利用 LINQ 中的表达式树的更通用和可重用的版本,请查看 Thomas Petricek 的博客文章:http ://tomasp.net/articles/dynamic-linq-queries.aspx