"where"子句:实体id位于可能为空的数组中

Mat*_*att 3 .net c# linq-to-entities entity-framework

我有一系列办公室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();
Run Code Online (Sandbox Code Playgroud)

抛出异常:

System.NotSupportedException : Cannot compare elements of type 'System.Int32[]'. Only primitive types (such as Int32, String, and Guid) and entity types are supported.
Run Code Online (Sandbox Code Playgroud)

特别是Linq to Entities反对officeIdsToSelect == null.我理解它的含义(一个更清晰的EF错误消息......)

那么我怎样才能得到我想要的东西呢?

ken*_*n2k 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();
}
Run Code Online (Sandbox Code Playgroud)

编辑:

如果您的实际查询更复杂并且您不想复制它,那么您可以做的是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();
Run Code Online (Sandbox Code Playgroud)

如果条件Where不覆盖原来的Where子句; 但是是附加的

是的,这是LINQ to Entities的强大功能:流畅的编程延迟执行.

流畅的编程意味着您可以链接方法,这可以通过LINQ实现,这要归功于IQueryable扩展方法.

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

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

有关查询执行机制的详细信息,请参阅此MSDN文章.