LINQ to SQL: Lambda-Ausdruck erneut verwenden

8

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.

    
Hannes Sachsenhofer 30.12.2010, 11:18
quelle

2 Antworten

18

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 ...

%Vor%

... 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.

%Vor%

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.

%Vor%

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%     
Joel Mueller 30.12.2010, 18:55
quelle
0

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.

    
Tomas Jansson 30.12.2010 11:33
quelle

Tags und Links