Laden...

Warum geht DefaultIfEmpty bei Linq LeftJoin nicht?

Letzter Beitrag vor einem Jahr 8 Posts 631 Views
Warum geht DefaultIfEmpty bei Linq LeftJoin nicht?

Hallo!

Ich dachte das wäre eine LeftJoin-Relation:

DVDEinträgeSort = (from DVD in DVDEinträge
                   join Reg in RegisseurListe.DefaultIfEmpty() on DVD.Regisseur equals Reg.ID
                   select new DVDEintragSort( DVD, new string((Reg.Nachname + ", " + Reg.Vorname).Trim()))).ToList(); 

Reg.ID und DVD.Regisseur sind vom Type long. Der Default-Wert müsste doch 0 sein.

Es werden jedoch alle Einträge der DVDEinträge-Liste die bei Regisseur den Wert 0 haben nicht übernommen.

Die RegisseurListe besitzt keinen Eintrag mit der ID 0.

Warum wirkt dann DefaultIfEmpty() nicht?

Du verwendest DefaultIfEmpty auf eine Liste von (offenbar) Objekten/Entitäten. Entsprechend ist der Default null und nicht 0.
Das solltest Du problemlos auch debuggen können.

Hallo perlfred,

du verwendest DefaultIfEmpty() an der falschen Stelle (dir fehlt noch ein into sowie eine weitere from-Klausel).

Schau dir die Beispiele unter Perform left outer joins und LINQ Left Join in C# mal genauer an.

Hallo Abt!

Das ist ja wieder mal so ein Denkfehler!!! Ja, ich muss natürlich den gesamten Eintrag sehen und nicht die Relationsverknüpfung und der Default eines Objektes ist dann natürlich null.

Auch das Debuggen ist ganz interessant! Allerdings gestaltet sich das Vorhaben bei rund 2000 Regisseur und 5000 DVD-Einträgen nicht so einfach. Mit Take() kommt man dann etwas weiter und sieht, dass erst alle Relations-Einträge komplett eingelesen werden und danach die DVD-Einträge iteriert werden und dieses Ergebnis dann im Select zurückgegeben wird.

Ich hatte dann folgenden Ansatz:

DVDEinträge = (List<DVDEintrag>)Erg_LoadDVDEinträgeListe.Daten;                   // Eingelesene DVD-Einträge-Liste übernehmen
DVDEinträgeSort = (from DVD in DVDEinträge
                   join Reg in RegisseurListe.DefaultIfEmpty() on DVD.Regisseur equals Reg.ID
                   select new DVDEintragSort( DVD, Reg != null ? (Reg.Nachname + ", " + Reg.Vorname).Trim() : "?")).ToList(); 

habe aber nie die 5.180 DVDEinträge in der DVDEinträgeSort-Liste erhalten (es waren immer 5.156 die 24 ohne Regisseur fehlen).

Ist also immer noch nicht ein LeftOuterJoin!

Ich werde mir mal den von Th69 vorgeschlagenen Link ansehen...

Vielen Dank für deine Hinweise!

Hallo Th69!

Das Ergebnis der Relation wird also erst noch einmal in einer Variablen gespeichert, die durch DefaultIfEmpty() auch null werden kann und dann wird das Select (auf Grundlage der Variable) ausgeführt:

DVDEinträgeSort =                                                                 // DVD-Einträge Sortierungs-Liste aktualisieren
                  (from DVD in DVDEinträge                                        // Left Data Source
                   join Reg in RegisseurListe on DVD.Regisseur equals Reg.ID      // Inner Join
                   into Group from Reg2 in Group.DefaultIfEmpty()                 // Performing Left Outer Join
                   select new DVDEintragSort(DVD,  Reg2 != null ? (Reg2.Nachname + ", " + Reg2.Vorname).Trim() : string.Empty)).ToList();

Das ist schon gewöhnungsbedürftig! 😉   Warum gibt es (in LINQ) nicht gleich einen LeftOuterJoin??? (Die Performing Left Outer Join - Zeile ist ja immer die Gleiche)

Vielen Dank! für deine Lösung, da war ich zu ungeduldig!

Zitat von perlfred

Warum gibt es (in LINQ) nicht gleich einen LeftOuterJoin??? (Die Performing Left Outer Join - Zeile ist ja immer die Gleiche)

Ne, ist sie nicht. DefaultIfEmpty gibt Dir eine Vielzahl von Optionen, die mit einem "einfachen" left outer join nicht möglich sind. Das merkst ja allein schon daran, wo Du DefaultIfEmpty überall einsetzen kannst.

Du hast einfach nur den simpelsten der simpelsten Fälle.

Hallo Abt!

Ich merke schon, dass ist wieder ein Feld, mit dem ich mich noch (viel) mehr beschäftigen muss! <schnauf> 😃

Aber steigern kann ich mich schon mit der nächsten Frage:  😃  😃

Wie setze ich denn mehrere LeftOuter Join's in einer Abfrage ???

DVDEinträgeSort =                                                                       // DVD-Einträge Sortierungs-Liste 
  (from DVD in DVDEinträge                                        // Left Data Source
   join Reg in RegisseurListe on DVD.Regisseur equals Reg.ID      // Inner Join Regisseure
   join Gen in GenreListe on DVD.Genre.First() equals Gen.ID      // Inner Join Genre
   into Gruppe from Reg2 in Gruppe.DefaultIfEmpty()               // Performing Left Outer Join

   select new DVDEintragSort(DVD,  Reg2 != null ? (Reg2.Nachname + ", " + Reg2.Vorname).Trim() : string.Empty), Gen.Bezeichnung).ToList();

Im Beispiel möchte ich aus der Regisseur und der Genre-Liste Daten (per LeftOuter Join) abfragen.

In Reg2 kommt jetzt der 2. Inner Join (Genre) an und Reg fehlt?.

Hallo!

Ich habe es jetzt so nach dem Ausschluss-Verfahren zwar hinbekommen, aber ... wie schon eingangs gesagt, muss ich mich damit beschäftigen.

DVDEinträgeSort =                                                                       // DVD-Einträge Sortierungs-Liste
    (from DVD in DVDEinträge                                        // Left Data Source
     join Reg in RegisseurListe on DVD.Regisseur equals Reg.ID      // Inner Join Regisseure
     into Gruppe from Reg2 in Gruppe.DefaultIfEmpty()               // Performing Left Outer Join
     join Gen in GenreListe on DVD.Genre.First() equals Gen.ID      // Inner Join Genre (1. Wert)
     into Gruppe2 from Gen2 in Gruppe2.DefaultIfEmpty()             // Performing Left Outer Join

      select new DVDEintragSort(DVD,  
            Reg2 != null ? (Reg2.Nachname + ", " + Reg2.Vorname).Trim() : string.Empty,
            Gen2 != null ? Gen2.Bezeichnung : string.Empty)
      ).ToList();
  1. Join mit Gruppe, dann 2. Join mit Gruppe, dann select.

Ob das der beste Weg ist? Ich bleib (notgedrungen) dran!