2016-11-11 1 views
0

Ich habe eine Liste und zwei Tabellen. (Dies ist eine sehr vereinfachte Version des aktuellen Schema, sollte aber für die Frage arbeiten)Linq Join-Abfrage mit linken äußeren Join werfen Objektreferenz nicht gefunden

List_A
FPI

Table_B
FPI_______NI
2_________1
4_________2

TABLE_C
NI_______Name
1_________x
2_________y

Meine Linq-Abfrage:

(from a in List_A 
join b in Table_B on a.FPI equals b.FPI into ab 
from b in ab.DefaultIfEmpty() 
join c in Table_C on b.FI equals c.FI into bc 
from c in bc.DefaultIfEmpty() 
select new { 
    FPI = a.FPI, 
    Name = c?.Name}).ToList(); 

dieser Code löst eine Ausnahme, dass Object reference not set to an instance of an object.. Nach einer Menge von Versuch und Experiment, habe ich zu einer Schlussfolgerung, dass in der zweiten Join, wenn ich tue b.FI equals c.FI, zu diesem Zeitpunkt ist es für die Einträge, für die es keinen Wert in der Tabelle_B ist fehlgeschlagen.

Die erwartete Ausgabe der Abfrage
ABC FPI____NI___Name
1_____null__null
2_____1_____x
3_____null__null
4_____2_____y


I kommt und bin nicht sicher, warum dieser Fehler sein sollte Was wäre die beste Lösung für dieses Problem.

+0

Mögliches Duplikat [Was für eine Nullreferenceexception ist, und wie kann ich es beheben?] (Http://stackoverflow.com/ Fragen/4660142/what-is-a-nullreferenceexception-and-how-do-i-fix-it) – mybirthname

+0

Ich habe das auch getan. Und ich habe sogar versucht, die Argumente zu entfernen, die eine Ausnahme auslösen könnten. –

Antwort

0

Ihre Anfrage würde perfekt gültig, wenn es sich um eine LINQ to Entities-Abfrage in SQL übersetzt wurde.

Da jedoch die Wurzel der Abfrage List_A ist das kein IQueryable ist, führt die gesamte Abfrage in LINQ to Objects Kontext, in dem Sie angeblich null Kontrollen auf der rechten Seite Variable des linken Außen überall verbinden auszuführen, einschließlich weitere Bedingungen beitreten.

So ist die einfache Lösung würde

join c in Table_C on b?.FI equals c.FI into bc 

Beachten Sie jedoch, mit, dass die Abfrage sehr ineffizient ist.Da es nach Enumerable Methoden aufgelöst wird, wird das ganze Table_B und Table_C in Speicher gelesen und dann verbunden.

Ein besserer Ansatz wäre, die db und im Speicher Anfragen zu trennen:

var dbQuery = 
    from b in Table_B 
    join c in Table_C on b.FI equals c.FI into bc 
    from c in bc.DefaultIfEmpty() 
    select new { b.FPI, c.Name }; 

var query = 
    from a in List_A 
    join bc in dbQuery on a.FPI equals bc.FPI into abc 
    from bc in abc.DefaultIfEmpty() 
    select new 
    { 
     FPI = a.FPI, 
     Name = bc?.Name 
    }; 

var result = query.ToList(); 
+0

Dank Ivan Stoev, das hat funktioniert. –

0

können Sie versuchen,

var list=(from a in Table_A 
       join b in Table_B on a.FPI equals b.FPI into ab 
       from b in ab.ToList() 
       join c in Table_C on b.NI equals c.NI into bc 
       from c in bc.DefaultIfEmpty() 
       select new { 
       FPI = a.FPI, 
       Name = c.Name}).ToList(); 

aktualisieren

  var list = (from a in Table_A 
        join b in Table_B on a.FPI equals b.FPI into ab 
        from b in ab.DefaultIfEmpty() 
        join c in Table_C on b == null ? 0 : b.NI equals c.NI into bc 
        from c in bc.DefaultIfEmpty() 
        select new 
        { 
         FBI = a.FPI, 
         NI = c != null ? c.NI : null,//if NI is nullable 
         //NI = c != null ? c.NI : 0,//if NI is not nullable 
         Name = c!=null?c.Name:null 

        }).ToList(); 
+0

Dies funktioniert ohne Ausnahme, aber gibt die Zeilen zurück, die Werte für die Spalte FPI in der Tabelle_B haben. Zweck dieser Abfrage ist es, einen linken Join zu erhalten. –

Verwandte Themen