2016-11-10 4 views
2

Ich versuche, explizit 3 Tabellen mit einem linken äußeren Join in einer Linq-Abfrage beitreten und läuft in Linq Parsing-Probleme. Das Ausführen einer inneren Verknüpfung wird korrekt analysiert und gibt Daten zurück, aber die Verwendung der linken äußeren Verbindung schlägt fehl.EntityFramework Linq Left Join Analysefehler - DotNet Core 1.0

Beispiel:

var query = from p in DatabaseContext.Products 
        where p.ClientID == clientID 
        join l in DatabaseContext.Licenses on p.ProductID equals l.ProductID into pl 
        from pli in pl.DefaultIfEmpty() 
        join a in DatabaseContext.Articles on p.ArticleID equals a.ArticleID into pa 
        from pai in pa.DefaultIfEmpty() 
        select new SomeEntityDTO 
        { 
         SomethingFromP = p.Something, 
         SomethingFromL = pli.Something, 
         SomethingFromA = pai.Something 
        }; 

Da beide verknüpften Tabellen Schlüssel der ersten Tabelle aus, I jeweils einzeln testen, indem die anderen verbinden, beispielsweise testen die Abfrage für P l und dann für P a . Diese Testabfragen funktionieren einwandfrei. Es ist auch möglich, die linke äußere Regel zu entfernen und ein korrektes Ergebnis zu erhalten.

var query = from p in DatabaseContext.Products 
        where p.ClientID == clientID 
        join l in DatabaseContext.Licenses on p.ProductID equals l.ProductID 
        join a in DatabaseContext.Articles on p.ArticleID equals a.ArticleID 
        select new SomeEntityDTO 
        ... the rest ... 

Anzeigen der säumige Abfrage in SQL Profiler (oben Codebeispiel) Ich sehe, dass die ersten beiden Tabellen erfolgreich verbunden sind, zB:

SELECT p.Something, l.Something 
FROM Products AS p 
LEFT JOIN Licenses AS l ON p.ProductID = l.ProductID 
WHERE p.ClientID = 5 
ORDER BY p.ProductID 

Und ein anderer, dann rechts nach dieser erfolgreichen Abfrage, sind 2 Abfragen (identisch zueinander):

SELECT a.ArticleID, a.Something, <all fields, even when not specified in query> 
FROM Articles AS a 
ORDER BY a.ArticleID 

die äußere verbundene 3-Tabellen erfolgreich ein Objekt zurückgeben, solange ich nicht versuchen, ein Feld aus dem „a“ Tabelle zuzugreifen. Wenn ich das tue, erhalte ich einen Null Exception Fehler, da diese Tabelle nie wirklich verbunden wurde.

Wie bereits erwähnt, wird durch das Entfernen der Outer-Join-Regel eine erfolgreich verknüpfte Abfrage zurückgegeben.

Ich habe versucht, die Linq-Abfrage einzustellen herauszufinden, dass der Linq-Parser ein Problem hatte, aber ohne Erfolg:

var query = from p in DatabaseContext.Products 
      from l in DatabaseContext.Licenses.Where(g => g.ProduktID == p.ProduktID).DefaultIfEmpty() 
      from a in DatabaseContext.Articles.Where(g => g.ArticleID == p.ArticleID).DefaultIfEmpty() 
      where .... 

Diese parst auf einen Satz von CROSS applys, die überhaupt nicht funktionieren und den Eine profilierte Abfrage wird, wenn sie in ein Abfrageeditorfenster kopiert wird, überhaupt nicht ausgeführt (im Gegensatz zu den 3 einzelnen Abfragen, die im Profiler für das erste Codebeispiel angezeigt werden). Ich habe auch die komplizierteren Lambdas versucht, die auch nicht funktionieren.

Ist das ein Fehler im Linq-Parser? Mache ich das völlig falsch? (Nach den mehrfach beantworteten Fragen hier zu expliziten linken Outer Joins (im Gegensatz zu natürlichen Assoziationen), mache ich das richtig, aber es wird nicht korrekt analysiert. Ich habe es vermieden, die Assoziationen zu erstellen, so dass ich ihnen ohne assoziieren kann explizite Definition der Join.The ist möglicherweise erforderlich hier und wird nicht ordnungsgemäß ohne es?

Hinweis: Jede Tabelle verfügt über komplexe Schlüssel, aber ich muss nur wirklich auf Basis einzelner Schlüssel Werte (die DB ist Teil eines Produkts ich kann es nicht ändern).

Verwendung. DotNet Core EntityFramework, EntityFrameworkCore.SqlServer usw., alle Version 1.0.1.

Hilfe?

+1

Es ist nicht deine Schuld. EF Core hat zu diesem Zeitpunkt immer noch Probleme mit linken Outer-Joins (und Abfragen im Allgemeinen). –

+0

@Ian Stoev Danke für die Antwort. Kann ich eine andere Syntax verwenden, die nachweislich funktioniert? Zumindest bis der Weg, den ich versuche, in einer zukünftigen Version behoben wird? – Greg

+0

AFAIK, leider nicht. Nur 'Include' funktioniert, Sie können SO nach ähnlichen Problemen suchen. Sie können auch versuchen 1.1 Beta, aber es sieht aus wie es auch instabil ist. –

Antwort

1

Die kurze Antwort ist, EF6 anstelle von EFCore zu verwenden, wenn Sie selbst nach der Version 1.1 unbedingt komplexe Linq-Abfragen auf Ihren Entities haben müssen. Es fehlen immer noch zu viele Dinge in EFCore im Vergleich zu EF6.

Roadmap here.

In meinem Fall habe ich EFCore behalten und die Context.Entity.FromSql (query) -Methode verwendet, um die Ergebnisse zu erhalten.Dies ermöglichte es mir, EFCore für die meisten EF-Entities zu verwenden und somit einen zukunftsorientierten Ansatz für die Anwendung zu verfolgen und gleichzeitig spezielle Ausnahmen für komplizierte Abfragen zuzulassen, die nicht auf einer tatsächlichen Entität basieren. Der Plan ist, diese FromSql-Abfragen zu ersetzen, wenn EF Core reift.

Bevor ich mich für .FromSql entschieden habe, habe ich auch eine Abfrage in einer Ansicht und in einer gespeicherten Prozedur getestet. In beiden Fällen habe ich versagt. Für gespeicherte Prozeduren sind benannte Parameter noch nicht implementiert und Sichten werden derzeit nicht unterstützt, es sei denn, Sie versuchen, EF dazu zu verleiten, zu denken, dass die Ansicht tatsächlich eine Tabelle ist (was zu eigenen Problemen führt).

Um EF-Core .FromSql zugreifen zu können, müssen Sie das folgende Paket installieren: Microsoft.EntityFrameworkCore.Relational

+0

Kannst du bitte erklären, dass "du versuchst, EF zu überreden, dass die Ansicht tatsächlich ein Tisch ist?" Ich habe zweimal Informationen über diesen "Trick" gesehen (dieser Kommentar zum Beispiel https://github.com/aspnet/EntityFramework/issues/ 245 # issementcomment-219787628), aber niemand sagt, wie sie es machen. – PilgrimViis

+1

@PilgrimViis Ich definiere es einfach so, wie ich eine Tabelle im Entity-Modell mit einer Table ("MyView") - Annotation definieren würde und stelle sicher, dass die View auch einen [Key] hat (einfach eine berechnete wie "DENSE_RANK() OVER (ORDER BY ...) ". – Greg

+0

für Informationen habe ich gerade mit Dotnet-Core gestartet und mit Framework-Core 1.0.1 war es fehlgeschlagen. Allerdings habe ich ein Update (1.1.0) bemerkt, installiert, und jetzt ein Tun a ' links 'verbinden die alten Entity Way Nähte funktionieren – beakersoft