Kompiliertes LINQ-zu-SQL-Abfrageproblem (funktioniert als nicht kompilierte Abfrage)

8

Ich habe C # -Erweiterungsmethoden für IQueryable , z. FindNewCustomers() und FindCustomersRegisteredAfter(int year) usw., die ich verwende, um eine Abfrage für LINQ to SQL zusammenzufassen.

Nun zu meinem Problem: Ich möchte kompilierte Abfragen erstellen, zum Beispiel:

%Vor%

Die Methode FindCustomersRegisteredAfter(int year) ist eine Erweiterungsmethode, die ein IQueryable übernimmt und dasselbe zurückgibt. Die Methode OrderBy ist ebenfalls eine Erweiterungsmethode (System.Linq.Dynamic), die einen dynamischen Ausdruck basierend auf einer Zeichenfolge erstellt (z. B. "FirstName ASC" wird das Feld FirstName aufsteigend sortieren). Skip und Take sind die integrierten Methoden.

Das obige (nicht als kompilierte Abfrage, aber normale Abfrage) funktioniert perfekt . Sobald ich es in eine kompilierte Abfrage einfügte, traf ich den folgenden Fehler:

Methode 'System.Linq.IQueryable'1 [Domain.Customer] FindCustomersRegisteredAfter [Customer] (System.Linq.IQueryable'1 [Domäne.Kunden], Int32)' hat keine unterstützte Übersetzung in SQL.

Dies funktioniert auch dann einwandfrei, wenn die Abfrage nicht kompiliert ist , nur eine normale LINQ-Abfrage. Der Fehler wird nur angezeigt, wenn er sich in CompiledQuery.Compile () befindet.

Hilfe ??!

Bearbeiten: Wenn ich die Abfrage über var query = (...) auf die gleiche Weise wie in CompiledQuery.Compile erzeuge, ist dies das generierte SQL:

%Vor%

Ihr seht also, dass das SQL alles perfekt übersetzbar ist, so dass ich nur @ p0, @ p1 und @ p2 ausfüllen muss, damit dies wiederholt funktioniert! Was stimmt nicht mit CompiledQuery.Compile?!?

Update: Ich verstehe, dass OrderBy nicht funktionieren kann (da es kein @ p-Parameter ist). Ich versuche immer noch herauszufinden, warum CompiledQuery.Compile nicht mit meinen Erweiterungsmethoden funktioniert. Informationen im Internet zu diesem Thema gibt es praktisch nicht.

    
Alex 09.08.2010, 07:32
quelle

1 Antwort

3

Ich glaube, dass die kompilierte Abfrage in SQL übersetzt werden muss, was Ihre Erweiterungsmethode nicht sein kann. Wenn Sie das von Ihrer "normalen" Abfrage erstellte SQL profilieren, stellen Sie möglicherweise fest, dass es die gesamte Tabelle auswählt, damit es alle Zeilen in Ihre Erweiterungsmethode einspeisen kann.

Sie sollten Ihre Filterlogik besser in die Abfrage einfügen (als Teil der Ausdrucksbaumstruktur), damit sie in SQL übersetzt und serverseitig ausgeführt werden kann.

Die OrderBy ist auch ein Problem wegen des Skip. Sie müssen dies übersetzbar in SQL oder LINQ müssen alle Zeilen zurückgeben, um sie clientseitig zu filtern.

Wenn Sie diese Ausdrücke nicht als LINQ-Ausdrücke ausdrücken können, sollten Sie in Erwägung ziehen, SQL-Funktionen auf dem Server zu erstellen und sie Ihrem DataContext zuzuordnen. LINQ kann diese in die T-SQL-Funktionsaufrufe übersetzen.

BEARBEITEN:

Ich nehme an, ich nahm an, dass Ihre Erweiterungsmethoden keine Ausdrucksbäume erstellen. Es tut uns leid.

Betrachten Sie diesen Link , der scheint Ihrem Problem ähnlich. Es verweist auf einen anderen Link , der ausführlicher behandelt wird.

Es sieht so aus, als ob der MethodCallExpression das Problem ist.

  

Der Code ist ein bisschen lang, um gepostet zu werden   hier, aber ähnlich wie bei tomasp.net   Expander, ich besuche jeden Ausdruck in   der Ausdrucksbaum und wenn der Knoten ist   eine MethodCallExpression, die a aufruft   Methode, die einen Ausdruck zurückgibt   Baum, ich ersetze das   MethodCallExpression durch den Ausdruck   Baum durch Aufruf der Methode zurückgegeben.

Das Problem scheint also so zu sein, dass die Methode beim Kompilieren der Abfrage nicht ausgeführt wird, so dass keine Ausdrucksbaumstruktur in SQL übersetzt werden muss.

    
ongle 15.09.2009, 12:57
quelle