EF6 Linq - 如何创建一个等同于"的过滤表达式(其中(List == null || List.Contains(obj))"?

时间:2016-12-29 16:42:51

标签: c# linq entity-framework-6

我尝试执行以下操作(SelectedIdCollection为List,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,   Version = 4.0.0.0,Culture = neutral,PublicKeyToken = b77a5c561934e089]]'。   只有原始类型,枚举类型和实体类型   支撑。

还有其他方法可以将这个写入条件吗?

2 个答案:

答案 0 :(得分:4)

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

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

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

答案 1 :(得分:2)

抛出异常是因为您正在比较运行时变量(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中这也可能更快,因为查询计划程序可能会选择不同的索引,如果它不需要读取所有要过滤的列。