Why does LINQ-to-EF display certain "Contains" as two separate JOINs?

Possible duplicate:
EF4.2 additional left outer join with the same table

I have three objects in Parent -> Child -> Grandchildren: Order -> OrderCustomer -> OrderItem

Each child has a non-existent FK for its parent (that is, OrderItem.OrderCustomerID and OrderCustomer.OrderID). And I want to query all OrderItems (grandchildren) for a group of Orders. In SQL, I would write:

select
    oc.OrderID,
    oi.Quantity,
    oi.SKU
from OrderItems oi
    join OrderCustomers oc on oi.OrderCustomerID = oc.OrderCustomerID
where
    oc.OrderID in (1, 2, 3, 4, 5)

      

... so this is what I wrote in LINQ ...

OrderItems
    .Where(oi => new[] { 1, 2, 3, 4, 5 }.Contains(oi.OrderCustomer.OrderID))
    .Select(oi => new
    {
        oi.OrderCustomer.OrderID,
        oi.Quantity,
        oi.SKU
    })

      

... but this is SQL generated by EF ...

SELECT 
    [Extent1].[OrderCustomerID] AS [OrderCustomerID], 
    [Extent3].[OrderID] AS [OrderID], 
    [Extent1].[Quantity] AS [Quantity], 
    [Extent1].[SKU] AS [SKU]
FROM [dbo].[OrderItems] AS [Extent1]
    INNER JOIN [dbo].[OrderCustomers] AS [Extent2] ON [Extent1].[OrderCustomerID] = [Extent2].[OrderCustomerID]
    LEFT OUTER JOIN [dbo].[OrderCustomers] AS [Extent3] ON [Extent1].[OrderCustomerID] = [Extent3].[OrderCustomerID]
WHERE
    [Extent2].[OrderID] = 1 OR [Extent3].[OrderID] IN (2,3,4,5)

      

Why both INNER JOIN and OUTER JOIN?

And why split the WHERE clause?

In a database with millions of records, this query is terribly slow.

But wait if I change LINQ to perform a selection before where ...

OrderItems
    .Select(oi => new
    {
        oi.OrderCustomer.OrderID,
        oi.Quantity,
        oi.SKU
    })
    .Where(x => new[] { 1, 2, 3, 4, 5 }.Contains(x.OrderID))

      

... I am getting the SQL I wanted ...

SELECT 
    [Extent1].[OrderCustomerID] AS [OrderCustomerID], 
    [Extent2].[OrderID] AS [OrderID], 
    [Extent1].[Quantity] AS [Quantity], 
    [Extent1].[SKU] AS [SKU]
FROM [dbo].[OrderItems] AS [Extent1]
    INNER JOIN [dbo].[OrderCustomers] AS [Extent2] ON [Extent1].[OrderCustomerID] = [Extent2].[OrderCustomerID]
WHERE
    [Extent2].[OrderID] IN (1,2,3,4,5)

      

So, I think I can help EF by doing LINQ Select first, but does anyone know what is involved with the first query?

+3


source to share





All Articles