我有一组办公室 ID,该数组可能为空。如果 officeIdsToSelect 数组为空,我希望 EF 查询返回所有记录,或者如果它不为空,则只返回匹配的记录。
然而这个:
int[] officeIdsToSelect = new int[] { 1, 2, 3 };
Office[] selectedOffices = (from item in new TdsDb().Offices
where (officeIdsToSelect == null || officeIdsToSelect.Contains(item.OfficeID))
select item).ToArray();
抛出异常:
System.NotSupportedException : Cannot compare elements of type 'System.Int32[]'. Only primitive types (such as Int32, String, and Guid) and entity types are supported.
特别是 Linq to Entities 反对
officeIdsToSelect == null
。我明白它在说什么(更清晰的 EF 错误消息之一......)那么我怎样才能在这里得到我想要的东西呢?
最佳答案
EF 无法将 officeIdsToSelect == null
转换为 SQL。
另一方面,EF 足够聪明,可以将 officeIdsToSelect.Contains(item.OfficeID)
转换为 WHERE OfficeID IN (1, 2, 3)
。
所以基本上,你可以简单地做:
Office[] selectedOffices;
if (officeIdsToSelect == null)
{
selectedOffices = new TdsDb().Offices.ToArray();
}
else
{
selectedOffices = (from item in new TdsDb().Offices
where officeIdsToSelect.Contains(item.OfficeID)
select item).ToArray();
}
编辑:
如果您的实际查询更复杂并且您不想复制它,您可以做的是根据您的
Where
数组的值有条件地添加一个 int
子句。// Here's a query that is NOT YET executed (deferred execution)
var query = (from item in new TdsDb().Offices
...... your whole complicated request here
select item);
// Conditionnally adds a where clause if required
if (officeIdsToSelect != null)
{
// Still not yet executing the query. We're just building the query for now
query = query.Where(z => officeIdsToSelect.Contains(z.OfficeID));
}
// OK, now executes the query and get the results
Office[] selectedOffices = query.ToArray();
是的,这就是 LINQ to Entities 的强大之处: 流畅编程 和 延迟执行 。
流利的编程意味着您可以链接方法,由于
IQueryable
扩展方法,这在 LINQ 中是可能的。例如,
IQueryable<T>.Where(...)
也返回一个 IQueryable<T>
对象。它在内部向查询添加谓词,然后返回您指定为参数的查询。另一个重要的部分是延迟执行。这允许 而不是 执行查询,直到实际请求数据。只有当您真正需要数据时,请求才会针对您的数据库实际执行。
在上面的示例中,实际执行查询的是
.ToArray()
命令。有关查询执行机制的详细信息,请参阅 this nice MSDN article。
关于c# - "where"子句 : entity id is in a potentially null array,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/16593257/