Why does EF translate a Contains method call to Exists clause instead of In Clause?

回眸只為那壹抹淺笑 提交于 2020-01-11 06:55:30

问题


When I create this query:

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

I Expect it to create a query like this:

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

But the generated query is equivalent to:

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

this is a very simple query which could be written as:

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

but my actual scenario cannot be. Also, for this simple query, the execution time is not different, but in more complex cases, the expected query runs much faster.

How can I force EF to use the query the way I want it to?


回答1:


My theory is that EF does not natively support Contains, but it does support Any. As a hack, it translates your expression into the equivalent Any expression, which translates into an Exists expression in Sql.

My problem with that approach is that the sql query is messier than it needs to be (your issue), and I have also found examples where the database cannot optimize as well as it could.

The workaround that I use is to replace the Contains with an inner Join. So your example becomes:

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

(Sorry, I know you are using lambda expressions but I'm not sure how to write joins using those).



来源:https://stackoverflow.com/questions/13475654/why-does-ef-translate-a-contains-method-call-to-exists-clause-instead-of-in-clau

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!