EF6 Linq - 如何创建等效于 "where(List == null || List.Contains(obj))" 的筛选器表达式?



我正在尝试执行以下操作(selectedIdCollection是列表,cb.id是int) -

db.Items.Where(cb => (SelectedIdCollection == null || SelectedIdCollection.Contains(cb.Id)))

基本上,如果SelectedIdCollection为null,则返回所有内容,如果它不是null,则通过它过滤。

,但会引发以下错误 -

类型" system.notsupportedexception"的例外发生在entityFramework.sqlserver.dll中,但未在用户代码中处理。不能 比较类型的元素 'System.Collections.generic.ilist'1 [[System.int32,Mscorlib, 版本= 4.0.0.0,文化=中性,publicKeyToken = B77A5C561934E089]]'。 只有原始类型,枚举类型和实体类型是 支持。

是否有其他方式写这条条件?

由于 SelectedIdCollection是从表达式外部捕获的变量,因此您可以在制作表达式之前处理它是 null,然后将其视为nonnull:

var getEverything = SelectedIdCollection==null;
var targetCollection = SelectedIdCollection ?? new int[0];
var res = db.Items.Where(cb => getEverything || targetCollection.Contains(cb.Id));

现在保证targetCollection是非nullgetEverything标志涵盖了需要从数据库中选择所有内容的条件。

因为您正在比较运行时变量(SelectedIdCollection != null),并且EF不知道如何将其转换为SQL。

您可以做这样的事情吗?

var items = db.Items.AsQueryable();
if(SelectedIdCollection != null)
{
   items = items.Where(cb => SelectedIdCollection.Contains(cb.Id));
}
if(date1 != null)
{
   items = items.Where(cb => cb.Date1 == date1);
}

这也可能在SQL中更快,因为查询计划者如果不需要读取所有列来过滤的索引。

最新更新