2010-11-24 8 views
0

Ein kleiner Hintergrund zur Abfrage unten. Zelle hat ein 1: M zu Container und ein 1: M mit Drucker. Ich möchte eine Abfrage, die alle Zellen und zugehörigen Container, sofern vorhanden, und die zugehörigen Drucker, sofern vorhanden, abrufen. Im Wesentlichen möchte ich eine linke äußere Verbindung auf beiden Tabellen tun. Hier ist die Abfrage, die ich habe:Wie macht man mehrere linke äußere Joins in einer Linq-Abfrage?

var query = from cell in Cell 
    join container in Container.Where (row => row.SerialNumber == "1102141") on cell.CellID equals container.CellID 
    into containers 

    join printer in Printer.Where (row => row.Name == "PG10RelWarrPrt3") on cell.CellID equals printer.CellID 
    into printers 

    select new { Cell = cell, Containers = containers, Printers = printers }; 

query.Dump(); 

Diese Abfrage funktioniert, ist aber nicht effizient. Es führt einen linken äußeren Join für Container aus, führt jedoch für jede Zelle eine separate Abfrage durch, um alle Druckerzeilen abzurufen, anstatt einen linken äußeren Join auf Printer auszuführen.

Wie kann ich dies ändern, so dass es auch eine linke äußere Verknüpfung in der Tabelle Printer macht? BTW, ich möchte eine hierarchische Ergebnismenge. IOW, jede Zelle sollte eine Liste von Containern und eine Liste von Druckern haben. Jeder wäre natürlich leer, wenn für die Zelle keiner existiert.

+1

http://stackoverflow.com/questions/267488/linq-to-sql-multiple-left-outer-joins – diceguyd30

+0

@ diceguyd30 - Ich sah, dass, bevor ich meine Frage gestellt. Das löst mein Problem nicht. Beachten Sie, dass ich sage, dass ich eine hierarchische Ergebnismenge haben möchte, nicht eine flache. DefaultIfEmpty() ist für flache Ergebnismengen. –

Antwort

2

Hier ist eine Abfrage, um ein flaches Ergebnis zu erzielen eingestellt mit dem richtigen links verbindet.

var query = from cell in Cell 
    join container in Container.Where (row => row.SerialNumber == "1102141") on cell.CellID equals container.CellID 
    into containers 
    from container2 in containers.DefaultIfEmpty() 
    join printer in Printer.Where (row => row.Name == "PG10RelWarrPrt3") on cell.CellID equals printer.CellID 
    into printers 
    from printer2 in printers.DefaultIfEmpty() 
    select new { Cell = cell, Container = container2, Printer = printer2 }; 

Sie müssen die Ergebnisse lokal nachbearbeiten, um die gewünschte hierarchische Form zu erhalten.

Wenn Sie diesen Post-Processing-Code schreiben, werden Sie verstehen, warum linq to sql mehrere Geschwister-Sammlungen für Sie nicht verarbeitet.


Um dies deutlicher zu machen, nehmen wir an, Sie hätten 3 Geschwisterkollektionen.

Wenn alle drei Geschwistersammlungen für einen übergeordneten Datensatz leer waren, haben Sie nur den übergeordneten Datensatz 1 Mal mit einer Reihe von Nullen.

Wenn alle drei Geschwisterkollektionen 100 Datensätze für einen übergeordneten Datensatz hätten, hätten Sie 1 Million Zeilen, jeweils mit einer Kopie des übergeordneten Datensatzes. Jeder untergeordnete Datensatz würde 10.000 Mal im Ergebnis dupliziert werden.

Es ist immer wichtig, bei jedem ORM zu berücksichtigen, dass es sql erzeugt und flache Ergebnismengen zurückbekommt, unabhängig davon, welches hierarchisch geformte Ergebnis es Ihnen letztendlich bietet.

1

It's usually wrong to use join in LINQ to SQL.

Versuchen:

var query = from cell in Cell 
      select new 
      { 
       Cell = cell, 
       Containers = cell.Containers 
           .Where (row => row.SerialNumber == "1102141"), 
       Printers = cell.Printers 
           .Where (row => row.Name == "PG10RelWarrPrt3") 
      }; 
+0

Das gibt mir die Ergebnismenge, die ich will, aber nicht das richtige T-SQL. Es erzeugt genau das gleiche T-SQL wie die Abfrage in meinem Post. Es führt einen linken äußeren Join in der Containertabelle und dann eine separate Abfrage in der Printer-Tabelle für jede Zeile in der Zelle Tabelle aus. Es macht nicht zwei linke äußere Joins. –

Verwandte Themen