2009-04-27 9 views
15

Ich habe eine Methode "hat keine Übersetzung in SQL", die ich auf einem IQueryable ausführen möchte, gibt es eine Möglichkeit, die Ausführung von IQueryable zu erzwingen, ohne es in einer Zwischenklasse zu speichern?Erzwingen, dass ein IQueryable ausgeführt wird?

+0

Dies ist eine blinde Vermutung, aber wenn string.IsNullOrEmpty der Schuldige ist, dann verwenden Sie 2 Where-Klauseln stattdessen:. Wo (o => o.Name! = Null). Wo (o => o.Name.Length> 0) . – mayu

Antwort

25

Ist das Problem, dass Ihre Methode lokal statt in der Datenbank ausgeführt werden soll? Wenn ja, AsEnumerable ist dein Freund. Es ist eine sehr einfache Methode, so etwas wie:

public IEnumerable<T> AsEnumerable(IEnumerable<T> source) 
{ 
    return source; 
} 

Das Wichtigste ist, dass es den Kompilierung-Typen des Ergebnisses IEnumerable<T> statt IQueryable<T>, die alle LINQ-Abfrage Operatoren bedeuten macht nach dem Aufruf, dass der LINQ sein zu Objects anstelle von LINQ to SQL.

Zum Beispiel:

var query = context.Employees 
        // Filtering performed in SQL 
        .Where(emp => emp.IsFullTime) 
        .AsEnumerable() 
        // Projection performed locally; ComputeSalary has no 
        // SQL equivalent 
        .Select(emp => new { Employee = emp, 
             Salary = ComputeSalary(emp) }); 

Sie könnten ToList nennen, wie an anderer Stelle vorgeschlagen, aber wenn Sie Filterung tun und nicht wirklich brauchen die voll Liste im Speicher, rufen AsEnumerable und Filterung dass Ergebnis wird effizienter sein, als alles zuerst zu laden.

+1

Führt diese Technik mit Linq auch zu EF? Es scheint nicht zu sein. – neontapir

+0

Ich verstehe nicht, was 'lokal ausführen statt in der Datenbank' bedeutet. Für diejenigen wie mich: IQueryable as = von einem in x wählen a; dann a.Count(); a.Foreach (...) führt zwei SQL-Abfragen aus. – mayu

+2

@Tymek: Ja, das Ausführen von zwei SQL-Abfragen. Aber mit "lokal ausführen" meine ich "alle Ergebnisse in der Abfrage so weit von der Datenbank holen, aber dann den Rest der Abfrage im Speicher durchführen" - so können Sie Filter, Projektionen usw. durchführen, die in SQL nicht anwendbar sind. –

6
List<Employees> myEmployees = myqueryable.ToList(); 

und dann können Sie Ihre linq Sachen auf dieser Liste tun.

2

Sie erhalten diese Nachricht, wenn Sie eine Abfrage geschrieben haben, dass LinqToSql nicht in SQL übersetzen kann (was es auch sagt).

Ich bin nicht sicher, ob ich genau das bekommen, was Sie fragen, aber soweit ich sehe, haben Sie folgende Möglichkeiten:

  1. Ihre Abfrage neu schreiben, so dass LinqToSql es
  2. Sie übersetzen kann als ein großer Teil der Abfrage, wie Sie auf dem SQL-Server kann dann im Speicher den Rest
  3. sich hinsetzen und weinen (Linq zu Objekten mit)

wir 3 # ausschließen Unter der Annahme, schauen wir uns die anderen aussehen 2 Beispiele.

  1. Umschreiben - um damit zu helfen, brauchen wir Ihre linq Abfrage.

  2. Hier nehmen Sie den Teil heraus, der nicht von der ursprünglichen Abfrage übersetzt werden kann, dann auf Ihre Iqueryable-Aufruf-ToList, und wenden Sie dann den Rest der Abfrage auf dieser Liste an.

Und können Sie die Abfrage ausführen, ohne sie zu speichern? Nun, nicht wirklich, Sie könnten die Ergebnisse immer durchlaufen und als solche nicht in einer Variablen speichern, aber offensichtlich müssen die Ergebnisse der Abfrage irgendwo gespeichert werden.

+1

Man muss sich nicht hinsetzen, um zu weinen. – mayu

+2

Sehr wahr - aber ich fühle, dass kein Mann im Stehen weinen sollte. Wenn du weinen musst, musst du es richtig machen. – kastermester