2012-04-04 11 views
6

Ich habe eine Datenzugriffsklasse, die mich eine Weile brauchte, um zu arbeiten. Für meine App muss ich verschiedene Typen von SQL Server-Tabellen abrufen, bei denen sich die WHERE-Klausel nur durch den Spaltennamen unterscheidet: Einige Spalten sind read_time, andere sind ReadTime und andere sind LastModifiedTime. Also dachte ich, ich würde die WHERE-Klausel übergeben, so dass ich keine neue Methode für 50 verschiedene Tabellen erstellen musste. Es sieht einfach aus, und es funktioniert, aber ich verstehe nichts.Warum sind Func <> und Expression <Func<>> austauschbar? Warum arbeitet man in meinem Fall?

Diese Methode, mit Expression <> als Parameter funktioniert:

internal List<T> GetObjectsGreaterThanReadTime<T>(Expression<Func<T, bool>> whereClause) where T : class 
{ 
    Table<T> table = this.Database.GetTable<T>(); 
    IEnumerable<T> objects = table.Where(whereClause); 

    return objects.ToList(); 
} 

Nun, ich war es auf diese Weise versuchen, (unten) für eine Weile, und es wäre in der letzten Zeile nur hängen (ToList()). Erstens, warum würde das kompilieren? Ich meine, warum können Expression und Func synonym als Parameter verwendet werden? Warum funktioniert Expression dann und die Func-Version hängt einfach?

Hinweis: Der einzige Unterschied zwischen der obigen Methode und diesem ist der Methodenparameter (Expression vs. Func).

internal List<T> GetObjectsGreaterThanReadTime<T>(Func<T, bool> whereClause) where T : class 
{ 
    Table<T> table = this.Database.GetTable<T>(); 
    IEnumerable<T> objects = table.Where(whereClause); 

    return objects.ToList(); 
} 
+3

Dies in Verbindung mit der Antwort (en) ist an sich eine sehr gute Antwort auf einige der "was ist der Sinn eines Ausdrucks Baum?" Art der Fragen. +1 Q & A –

Antwort

12

Die Expression Version ruft Queryable.Where, die einen Ausdrucksbaum erzeugt, die (wenn sie von ToList aufgezählt) zu SQL übersetzt wird und auf dem Datenbankserver ausgeführt wird. Vermutlich wird der Datenbankserver basierend auf den Filterkriterien einen Index verwenden, um das Lesen der gesamten Tabelle zu vermeiden.

Die Func Version ruft Enumerable.Where, die (wenn sie von ToList aufgezählt) die gesamte Tabelle lädt (was Sie als Hang wahrnehmen) und führt dann die Filterkriterien gegen die In-Memory-Objekte.

+0

Ahhhhhhhhhhhh ... NICE. Macht Sinn. Vielen Dank! –

Verwandte Themen