3

我有一组办公室 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 错误消息之一......)

那么我怎样才能在这里得到我想要的呢?

4

2 回答 2

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 的强大功能:流畅的编程延迟执行

流利的编程意味着您可以链接方法,这在 LINQ 中是可能的,这要归功于IQueryable扩展方法。

例如,IQueryable<T>.Where(...)还返回一个IQueryable<T>对象。它在内部向查询添加谓词,然后返回您指定为参数的查询。

另一个重要部分是延迟执行。这允许在实际请求数据之前执行查询。只有当您真正需要数据时,才会对您的数据库实际执行请求。在上面的示例中,它.ToArray()是实际执行查询的命令。

有关查询执行机制的详细信息,请参阅这篇漂亮的 MSDN 文章

于 2013-05-16T17:05:26.903 回答
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();
于 2013-05-17T05:33:35.497 回答