views:

45

answers:

2

I was wondering if anyone knew why linq to entities always seems to generate left outer joins. I would understand it on an optional relationship but it doesn't make good sense when the relationship is mandatory.

Does anyone have any idea how to make it generate inner joins instead?

A: 

You can create inner joins. You simply need to use the join keyword. For example, here is a query against the AdventureWorks database:

var query = from od in db.SalesOrderHeader
            join c in db.Customer on od.Customer.CustomerID equals c.CustomerID
            select new { c.AccountNumber, od.OrderDate };

The equivalent SQL:

Select C.AccountNumber, OD.OrderDate 
From Sales.SalesOrderHeader As OD
    Join Sales.Customer As C
        On C.CustomerID = OD.CustomerID

And here is the SQL that the LINQ query produced:

SELECT 
1 AS [C1], 
[Extent2].[AccountNumber] AS [AccountNumber], 
[Extent1].[SalesOrderID] AS [SalesOrderID], 
[Extent1].[RevisionNumber] AS [RevisionNumber], 
[Extent1].[OrderDate] AS [OrderDate], 
[Extent1].[DueDate] AS [DueDate], 
[Extent1].[ShipDate] AS [ShipDate], 
[Extent1].[Status] AS [Status], 
[Extent1].[OnlineOrderFlag] AS [OnlineOrderFlag], 
[Extent1].[SalesOrderNumber] AS [SalesOrderNumber], 
[Extent1].[PurchaseOrderNumber] AS [PurchaseOrderNumber], 
[Extent1].[AccountNumber] AS [AccountNumber1], 
[Extent1].[CreditCardApprovalCode] AS [CreditCardApprovalCode], 
[Extent1].[SubTotal] AS [SubTotal], 
[Extent1].[TaxAmt] AS [TaxAmt], 
[Extent1].[Freight] AS [Freight], 
[Extent1].[TotalDue] AS [TotalDue], 
[Extent1].[Comment] AS [Comment], 
[Extent1].[rowguid] AS [rowguid], 
[Extent1].[ModifiedDate] AS [ModifiedDate], 
[Extent1].[BillToAddressID] AS [BillToAddressID], 
[Extent1].[ContactID] AS [ContactID], 
[Extent1].[ShipMethodID] AS [ShipMethodID], 
[Extent1].[CreditCardID] AS [CreditCardID], 
[Extent1].[CurrencyRateID] AS [CurrencyRateID], 
[Extent1].[CustomerID] AS [CustomerID], 
[Extent1].[SalesPersonID] AS [SalesPersonID], 
[Extent1].[TerritoryID] AS [TerritoryID]
FROM  [Sales].[SalesOrderHeader] AS [Extent1]
INNER JOIN [Sales].[Customer] AS [Extent2] ON ([Extent1].[CustomerID] = [Extent2].[CustomerID]) OR (([Extent1].[CustomerID] IS NULL) AND ([Extent2].[CustomerID] IS NULL))
Thomas
You can easily make the EF use INNER JOINs without using `join` and [it's usually wrong to use join in L2E](http://blogs.teamb.com/craigstuntz/2010/01/13/38525/).
Craig Stuntz
@Craig Stuntz - Your article does not provide a compelling argument as to why `join` should not be used beyond syntactic preference in either L2S or L2E. Is there a significant performance difference? Is there a series of queries that cannot be written with the `join` syntax? Is the only reason that one can be a bit more verbose?
Thomas
I thought I was pretty clear about this: Using `join` does the same thing as not using it, except with twice the typing and half the readability and maintainability. It has no advantage whatsoever in cases where navigations could be used.
Craig Stuntz