我有一组office ID,数组可能为null。如果officeIdsToSelect数组为null,我希望EF查询返回所有记录,如果不是null,则返回匹配记录。 但是这个:
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错误信息......)
那么我怎样才能得到我想要的东西呢?
答案 0 :(得分:6)
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();
如果条件Where不覆盖原来的Where子句; 但是是附加的
是的,这是LINQ to Entities的强大功能:流畅的编程和延迟执行。
Fluent编程意味着您可以链方法,这可以通过IQueryable
扩展方法使用LINQ实现。
例如,IQueryable<T>.Where(...)
也返回IQueryable<T>
个对象。它在内部向查询添加谓词,然后返回您指定为参数的查询。
另一个重要的部分是延迟执行。这允许不执行查询,直到实际请求数据。只有当您确实需要实际执行的数据对数据库的数据时。
在上面的示例中,它是实际执行查询的.ToArray()
命令。
有关查询执行机制的详细信息,请参阅this nice MSDN article。
答案 1 :(得分:0)
试试这个;
int[] officeIdsToSelect = new int[] { 1, 2, 3 };
var selectedOfficeCount = officeIdsToSelect.Count;
Office[] selectedOffices = (from item in new TdsDb().Offices
where (selectedOfficeCount == 0 || officeIdsToSelect.Contains(item.OfficeID))
select item).ToArray();