views:

20329

answers:

4

I'm having some trouble figuring out how to use more than one left outer join using LINQ to SQL. I understand how to use one left outer join. I'm using VB.NET. Below is my SQL syntax.

T-SQL

SELECT
    o.OrderNumber,
    v.VendorName,
    s.StatusName
FROM
    Orders o
LEFT OUTER JOIN Vendors v ON
    v.Id = o.VendorId
LEFT OUTER JOIN Status s ON
    s.Id = o.StatusId
WHERE
    o.OrderNumber >= 100000 AND
    o.OrderNumber <= 200000
+1  A: 

I think you should be able to follow the method used in this post. It looks really ugly, but I would think you could do it twice and get the result you want.

I wonder if this is actually a case where you'd be better off using DataContext.ExecuteCommand(...) instead of converting to linq.

Jon Norton
+22  A: 

Don't have access to VisualStudio (I'm on my Mac), but using the information from http://bhaidar.net/cs/archive/2007/08/01/left-outer-join-in-linq-to-sql.aspx it looks like you may be able to do something like this:

var query = from o in dc.Orders
            join v in dc.Vendors on o.VendorId equals v.Id into ov
            from x in ov.DefaultIfEmpty()
            join s in dc.Status on o.StatusId equals s.Id into os
            from y in os.DefaultIfEmpty()
            select new { o.OrderNumber, x.VendorName, y.StatusName }
tvanfosson
@tvanfosson: what opinion do you have of using lamda expressions for defining the joins?
Amir
Do you mean extensions methods? That's probably would how I would do it now. I don't often use the LINQ syntax any more.
tvanfosson
would you mind updating your answer to show the extension method approach or linking to my answer at the bottom? Just want the world to know both ways :-)
Amir
+7  A: 

I figured out how to use multiple left outer joins in VB.NET using LINQ to SQL:

Dim db As New ContractDataContext()

Dim query = From o In db.Orders _
            Group Join v In db.Vendors On v.VendorNumber Equals o.VendorNumber Into ov = Group _
            From x In ov.DefaultIfEmpty() _
            Group Join s In db.Status On s.Id Equals o.StatusId Into os = Group _
            From y In os.DefaultIfEmpty() _
            Where o.OrderNumber >= 100000 And o.OrderNumber <= 200000 _
            Select Vendor_Name = x.Name, _
                   Order_Number = o.OrderNumber, _
                   Status_Name = y.StatusName
Bryan Roth
@Bryan: great linq to sql question, consider using lambda expressions to simplify the linq statement (you can get rid of the "into" clauses and really clean up the linq statement)
Amir
@aikr473: Good point. Thanks.
Bryan Roth
+38  A: 

This may be cleaner (you dont need all the into statements):


var query = 
    from order in dc.Orders
    from vendor 
    in dc.Vendors
         .Where(v => v.Id == order.VendorId)
         .DefaultIfEmpty()
    from status 
    in dc.Status
         .Where(s => s.Id == order.StatusId)
         .DefaultIfEmpty()
    select new { Order = order, Vendor = vendor, Status = status } 
    //Vendor and Status properties will be null if the left join is null

Amir
How does the generated SQL look like ? Doesn't it contains nested select this way ?
Manitra Andriamitondra
@manitra: No, you actually get LEFT OUTER JOIN statements (no nested selects). Pretty crazy huh?
Amir
Great news because, this syntax is quite clear :)
Manitra Andriamitondra
I like this approach better than using all the into statements. Thanks for posting this!
Bryan Roth