Ich bin über ein seltsames LINQ to SQL-Verhalten gestolpert - kann irgendjemand etwas dazu sagen?
Ich möchte einen Lambda-Ausdruck definieren und in meiner LINQ-Anweisung verwenden. Der folgende Code funktioniert einwandfrei:
%Vor%Aber wenn ich versuche, meinen Lambda-Ausdruck in einer Anweisung auf einer verknüpften Tabelle zu verwenden
%Vor%Ich bekomme eine Ausnahme:
%Vor%Aber, und das bekomme ich nicht: Es funktioniert gut, wenn ich mein Lambda direkt in die Abfrage lege:
%Vor%WARUM?!
Danke.
Okay, hier ist der Deal: dataContext.Table1s
hat den Typ IQueryable<T>
. IQueryable<T>
definiert die Methoden Where
und Any
, die ein Prädikat vom Typ Expression<Func<T, bool>>
verwenden. Der Expression<>
-Wrapper ist kritisch, da LINQ to SQL Ihren Lambda-Ausdruck in SQL übersetzen und auf dem Datenbankserver ausführen kann.
Allerdings enthält IQueryable<T>
auch IEnumerable<T>
. IEnumerable<T>
definiert auch Where
und Any
Methoden, aber die IEnumerable Version verwendet ein Prädikat vom Typ Func<T, bool>
. Da dies eine kompilierte Funktion und kein Ausdruck ist, kann sie nicht in SQL übersetzt werden. Als Ergebnis dieser Code ...
... zieht JEDEN Datensatz aus Table1s
in den Speicher und filtert dann die Datensätze im Speicher. Es funktioniert, aber es ist wirklich eine schlechte Nachricht, wenn Ihr Tisch groß ist.
Diese Version hat zwei Lambda-Ausdrücke. Der zweite, der direkt in Where
übergeben wird, ist ein Expression
, der einen Verweis auf ein Func
enthält. Sie können die beiden nicht kombinieren, und die Fehlermeldung, die Sie erhalten, sagt Ihnen, dass der Aufruf von Any
eine Expression
erwartet, Sie aber eine Func
übergeben.
In dieser Version wird Ihr inneres Lambda automatisch in ein Expression
konvertiert, da dies die einzige Möglichkeit ist, wenn Sie Ihren Code durch LINQ to SQL in SQL transformieren wollen. In den anderen Fällen erzwingen Sie, dass das Lambda ein Func
anstatt eines Expression
ist - in diesem Fall ist es nicht so, also funktioniert es.
Was ist die Lösung? Es ist eigentlich ziemlich einfach:
%Vor% Bezieht sich Table1
auf denselben Namespace? Im ersten Beispiel fragen Sie nach den Objekten Table1
, die sich direkt unter dataContext
befinden, im zweiten Beispiel nach den Objekten Table1
, die eine Eigenschaft der Objekte Table2
sind, und in Letztes Beispiel: Sie verwenden eine anonyme Funktion, die das Problem behebt.
Ich würde den Typ der Table1
-Objekte nachschlagen, der eine Eigenschaft eines Table2
-Objekts ist, und es mit einem Table1
-Objekt vergleichen, das direkt mit dem dataContext
verbunden ist. Meine Vermutung ist, dass sie sich unterscheiden und Ihr Lambda-Ausdruck den Typ des Objekts verwendet, das mit dataContext
verbunden ist.
Tags und Links linq-to-sql