2009-03-31 14 views
121

Ist diese Abfrage gleichbedeutend mit einer LEFT OUTER Verknüpfung?LINQ zu SQL Left Outer Join

//assuming that I have a parameter named 'invoiceId' of type int 
from c in SupportCases 
let invoice = c.Invoices.FirstOrDefault(i=> i.Id == invoiceId) 
where (invoiceId == 0 || invoice != null)  
select new 
{ 
     Id = c.Id 
     , InvoiceId = invoice == null ? 0 : invoice.Id 
} 

Antwort

141

Nicht ganz - da jeder „links“ Zeile in einem linksAußen beitreten 0-n „rechts“ Zeilen (in der zweiten Tabelle) entspricht, wo-wie Sie paßt nur 0-1. Gehen Sie eine linke äußere Verknüpfung, müssen Sie SelectMany und DefaultIfEmpty, zum Beispiel:

var query = from c in db.Customers 
      join o in db.Orders 
       on c.CustomerID equals o.CustomerID into sr 
      from x in sr.DefaultIfEmpty() 
      select new { 
       CustomerID= c.CustomerID, ContactName=c.ContactName, 
       OrderID = x.OrderID == null ? -1 : x.OrderID}; 

(or via the extension methods)

+4

LINQ to Entities erkennt die Methode DefaultIfEmpty ... –

+13

Kann jemand erklären, wie diese verrückte Syntax funktioniert? Ich kann nicht sehen, wie irgendeines dieser Schlüsselwörter es magisch zu einem Linksbündnis macht. Was macht das "in sr"? Linq frustriert mich manchmal :) –

+1

@JoePhillips Ich habe viel SQL-Erfahrung, aber zu versuchen LINQ zu lernen ist wie durch Matsch waten. Ich stimme zu, dass es absolut verrückt ist. –

12
Public Sub LinqToSqlJoin07() 
Dim q = From e In db.Employees _ 
     Group Join o In db.Orders On e Equals o.Employee Into ords = Group _ 
     From o In ords.DefaultIfEmpty _ 
     Select New With {e.FirstName, e.LastName, .Order = o} 

ObjectDumper.Write(q) End Sub 

prüfen http://msdn.microsoft.com/en-us/vbasic/bb737929.aspx

+0

Netter Versuch, aber es sieht aus wie das OP C# verwendet. Die VB-Syntax ist merkwürdig anders. – Levitikon

+3

+1 Einfach weil dies ein gutes vb.net Beispiel ist – twoleggedhorse

4

I 1 Lösung gefunden. wenn diese Art von SQL zu übersetzen (LEFT JOIN) in Linq Entity ...

SQL:

SELECT * FROM [JOBBOOKING] AS [t0] 
LEFT OUTER JOIN [REFTABLE] AS [t1] ON ([t0].[trxtype] = [t1].[code]) 
            AND ([t1]. [reftype] = "TRX") 

LINQ:

from job in JOBBOOKINGs 
join r in (from r1 in REFTABLEs where r1.Reftype=="TRX" select r1) 
      on job.Trxtype equals r.Code into join1 
from j in join1.DefaultIfEmpty() 
select new 
{ 
    //cols... 
} 
+0

Siehe [diesen Kommentar] (http://stackoverflow.com/questions/700523/linq-to-sql-left-outer-join#comment21835463_700580), Linq-to -SQL-Entitäten unterstützen "DefaultIfEmpty" nicht. –

177

Sie brauchen nicht die in Aussagen:

var query = 
    from customer in dc.Customers 
    from order in dc.Orders 
     .Where(o => customer.CustomerId == o.CustomerId) 
     .DefaultIfEmpty() 
    select new { Customer = customer, Order = order } 
    //Order will be null if the left join is null 

Und ja, die Abfrage oben erstellen ist in der Tat ein LEFT OUTER JOIN .

Link zu einer ähnlichen Frage, die mehrere linke Griffe verbindet: Linq to Sql: Multiple left outer joins

+10

Während ich weiß, dass die Antwort von @Marc Gravvel funktioniert, bevorzuge ich diese Methode, weil IMO sich eher an den Links-Joins orientiert. – llaughlin

+1

Ausgezeichnete Antwort. Auf der Suche nach mehr als 5 Stunden Google-Suche. Dies ist die einzige Möglichkeit, die sich daraus für SQL ergibt. –

+1

DANKE soooo viel .... Ich war den ganzen Nachmittag auf der Suche nach einer Lösung und Ihr Code hat es genagelt (und fühlt sich natürlich an). Ich wünschte, ich könnte das mehrmals wiederholen. – Jim

1

Ich möchte noch etwas hinzufügen. In LINQ to SQL müssen Sie, wenn Ihre Datenbank ordnungsgemäß erstellt wurde und Ihre Tabellen über Fremdschlüsseleinschränkungen miteinander verknüpft sind, keine Verknüpfung durchführen.

Mit LINQPad Ich habe die folgende LINQ-Abfrage:

//Querying from both the CustomerInfo table and OrderInfo table 
from cust in CustomerInfo 
where cust.CustomerID == 123456 
select new {cust, cust.OrderInfo} 

die mit dem (leicht abgeschnitten) Abfrage unter

-- Region Parameters 
DECLARE @p0 Int = 123456 
-- EndRegion 
SELECT [t0].[CustomerID], [t0].[AlternateCustomerID], [t1].[OrderID], [t1].[OnlineOrderID], (
    SELECT COUNT(*) 
    FROM [OrderInfo] AS [t2] 
    WHERE [t2].[CustomerID] = [t0].[CustomerID] 
    ) AS [value] 
FROM [CustomerInfo] AS [t0] 
LEFT OUTER JOIN [OrderInfo] AS [t1] ON [t1].[CustomerID] = [t0].[CustomerID] 
WHERE [t0].[CustomerID] = @p0 
ORDER BY [t0].[CustomerID], [t1].[OrderID] 

Hinweis übersetzt wurde die LEFT OUTER JOIN oben.