问题
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