假设我想根据用户提取的某些条件过滤客户列表。例如,假设他们可以将文本输入到多个文本框中的任何一个文本框中,并搜索该文本(例如,按客户名称,国家/地区等进行搜索)。
我可以做类似以下的事情......
IEnumerable<Customer> matches = customers; // start off with the full list
if (!string.IsNullOrWhiteSpace(customerName)) {
matches = matches.Where(c => c.Name.Contains(customerName));
}
if (!string.IsNullOrWhiteSpace(customerCountry)) {
matches = matches.Where(c => c.Country.Contains(customerCountry));
}
这样做,并且非常易读。
另一方面,我可以做以下事情......
List<Predicate<Customer>> predicates = new List<Predicate<Customer>>{
c => string.IsNullOrWhiteSpace(customerName) || c.Name.Contains(customerName),
c => string.IsNullOrWhiteSpace(customerCountry) || c.Country.Contains(customerCountry)
};
IEnumerable<Customer> matches = numbers.Where(n => predicates.All(p => p(n)))
如其中一个答案中所述,上述代码在每种情况下都冗余地检查string.IsNullOrWhiteSpace(customerName)。请忽略这一点,而不是花时间重写代码以解决副作用问题。
一个人对另一个人有什么好处吗?如果没有,我何时会使用谓词?
答案 0 :(得分:1)
至少,这一个:
c => string.IsNullOrWhiteSpace(customerName) || c.Name.Contains(customerName)
假设,将为每个列表项检查string.IsNullOrWhiteSpace(customerName)
,而第一个仅检查一次。
答案 1 :(得分:0)
虽然它实际上看起来并不令人生畏。但想象一下,你在一家IT公司工作,你的老板要求你创建一个应用程序,你可以根据公司数据库中的任何可用标准搜索所有员工。好吧那并不难你有一个Employees表,你只需要搜索那里的字段。所以你创建一个应用程序并连接你的文本框来提供你的价值,并根据你查询数据库。你的老板很高兴,但仍然没有现在他很满意他希望你的应用程序基于多个列进行查询 - 以任何顺序并可能全部使用它们。因此,您允许用户从复选框列表中选择将包含在查询中的任何字段,并指定条件。解决此问题而不使用LINQ和PredicateBuilder基本上需要为每个编写查询变体列的可能组合。
PredicateBuilder只是简单地结合了不确定数量的标准。因此,当您向数据访问层编写代码时,您可能不希望更改整个代码,而只需更改谓词构建器类。
答案 2 :(得分:0)
在玩了这个之后,我发现两者之间存在重大差异,所以除非有人能指示我这样做,否则我不认为你可以使用Linq2Entities的谓词方法。
我创建了一个新的控制台应用程序,添加了连接到Chinook数据库的EF模型,并添加了以下代码......
using (ChinookEntities ctx = new ChinookEntities()) {
List<Func<Album, bool>> predicates = new List<Func<Album, bool>> {
a => a.Title.Contains("AC"),
};
List<Album> albums = ctx.Albums.Where(c => predicates.All(p => p(c))).ToList();
}
}
当您尝试运行此操作时,会出现以下异常...
&#34;无法创建类型&#39; System.Func`2 [[Chinook.Album,Chinook,Version = 1.0.0.0,Culture = neutral,PublicKeyToken = null]的常量值, [System.Boolean,mscorlib,Version = 4.0.0.0,Culture = neutral,PublicKeyToken = b77a5c561934e089]]&#39;。在此上下文中仅支持原始类型或枚举类型。&#34;
看起来Linq2Entities并不支持这种方法 - 除非有人能告诉我如何解决这个问题。
希望这有助于某人。