为什么EF将Contains方法调用转换为Exists子句而不是In Clause?

时间:2012-11-20 14:44:34

标签: entity-framework

创建此查询时:

context.Orders.Where(x => context.Customers.Where(c => c.PersonID == 
10002).Select(c => c.CustomerID.Value).Contains(x.CustomerID.Value)).ToList();

我期待它创建一个这样的查询:

select * from Orders where CustomerID in (select CustomerID from Customers 
Where PersonID = 10002)

但生成的查询等同于:

select * from Orders o where Exists(select 1 from Customers c where
c.PersonID = 10002 and c.CustomerID = o.CustomerID)

这是一个非常简单的查询,可以写成:

context.Orders.Where(x => x.Customer.PersonID == 10002).ToList()

但我的实际情况不可能。此外,对于这个简单的查询,执行时间并没有不同,但在更复杂的情况下,预期的查询运行得更快。

如何强制EF以我想要的方式使用查询?

1 个答案:

答案 0 :(得分:2)

我的理论是,EF本身不支持Contains,但支持Any。作为一个hack,它将您的表达式转换为等效的Any表达式,该表达式转换为Sql中的Exists表达式。

我遇到的问题是sql查询比它需要的更麻烦(你的问题),而且我也找到了数据库无法优化的例子。

我使用的解决方法是将Contains替换为内部Join。所以你的例子就变成了:

from c in context.Customers
join o in context.Orders on o.CustomerId equals c.CustomerId
where c.PersonId = 10002
select o;

(抱歉,我知道你使用的是lambda表达式,但我不知道如何使用这些表达式编写联接。)