2012-06-14 14 views
5

Ich habe folgende Fragen gefunden, die mehrere Expression<Func<T,bool>> Ausdrücke kombinieren:SortiertNach Expression mit denen die Expression

How to merge two C# Lambda Expressions without an invoke?

Ich frage mich, ob, unter Verwendung einer ähnlichen Technik, wie Sie gehen über eine .OrderBy verschmelzenden Expression<Func<Entity, Key>> mit einem .Where Expression<Func<Entity, bool>> in einen Ausdruck des Typs oder erben vom Typ, System.Linq.Expressions.Expression.

Ich mache eine wirklich geschnittene QueryProvider-style-Klasse für die Übernahme T => T == ... Func's über öffentliche Methoden .Where und .OrderBy. Dies ist in der Absicht, dass der Ausdruck, den diese Klasse erstellt, an einen QueryTranslator übergeben wird, um geeignetes SQL zu erzeugen.

Ein QueryTranslator dieses Stils benötigt, wenn er von einem QueryProvider aufgerufen wird, normalerweise ein System.Linq.Expressions.Expression als Argument, das er dann in SQL übersetzt.

Ich kann die obige Frage für die Zusammenführung von zwei .Where Funcs durch und verstehen. In der folgenden Blog-Post war besonders nützlich für diese, und ich durch jeden der Beispiele verfolgt:

http://blogs.msdn.com/b/meek/archive/2008/05/02/linq-to-entities-combining-predicates.aspx

Dieser Artikel Codeproject war auch nützlich:

http://www.codeproject.com/Articles/24255/Exploring-Lambda-Expression-in-C

Wenn eine .OrderBy Func Kombination Bei einem .Where Func haben die beiden jedoch unterschiedliche generische Argumente. Im Falle der .Where ist es eine Func<Entity, bool>, und im Falle der .OrderBy ist es eine Func<Entity, Key>.

Das Zusammenführen dieser beiden Ausdrücke an der Oberfläche ist nicht so einfach wie das Zusammenführen von zwei mit denselben generischen Argumenten.

Die eingebaute Func-Expression-Engine (unsicherer Begriff) ist in der Lage, ein .Where Func mit einem .OrderBy Func zu kombinieren. Ich bin neugierig darauf, was unter der Haube passiert, wenn diese beiden Ausdrücke zusammengeführt werden, um eins zu werden System.Linq.Expressions.Expression. Ist es möglich, und wenn ja, wie würdest du eine Expression<Func<Entity, bool>> mit einer Expression<Func<Entity,Key>> kombinieren, wenn man annimmt, dass die Entity vom selben Typ in jedem Ausdruck ist?

+0

Wie sollte der resultierende Ausdruck aussehen? – dtb

+0

Es sollte dasselbe sein wie ein .Where (T => T.Name == "Cooper"). OrderBy (T => T.DateOfBirth) – Anthony

+1

Sie fusionieren '. Wo (x => condition1). Wo (x = > condition2) 'to' .Where (x => condition1 && condition) 'aber Sie können' .Where (x => condition) .OrderBy (x => value) 'nicht im selben Sinne zusammenführen. Also, wie sollte der resultierende Ausdruck aussehen? 'queryable.Where (x => condition) .OrderBy (x => value)' gibt keinen Ausdruck zurück, sondern gibt ein 'IQueryable ' zurück. – dtb

Antwort

3
public IQueryable<T> ApplyExpressions<T, TKey>(
    Expression<Func<T, TKey>> sortBy, 
    Expression<Func<T, bool>> filterBy, 
    IQueryable<T> source) 
{ 
    return source.Where(filterBy).OrderBy(sortBy); 
} 


IQueryable<Customer> query = ApplyExpressions<Customer, int>(
    c => c.Age, 
    c => c.Name.StartsWith("B"), 
    myDC.Customers) 

Expression queryExpression = query.Expression; //tada 
+0

Ich mag die Direktheit, aber es ist nicht ganz das, wonach ich suche. Ich habe keine Quelle zur Verfügung, also gibt es nichts, worüber man auf diese Weise nachdenken könnte. – Anthony

0

Ich denke, wo diese Frage mehrdeutig ist, ist, weil es irgendwie unbeantwortbar ist.

Ich habe versucht, einen Super-Ausdruck zu erstellen, wie die IQueryable<> Ausdruckserstellung mit .Where und .OrderBy Ausdrücke alle in einem Ausdruck funktioniert.

Ohne ein Thema scheint jedoch mein begrenztes Verständnis von Expressions und Expression Trees darauf hindeutet, dass es nicht möglich ist.

Um einen .Where Ausdruck mit einem .OrderBy Ausdruck in einem Ausdruck kombinieren Sie benötigen MethodCallExpression ‚s die beiden LambdaExpression s zu trennen.

Die MethodCallExpression benötigt einen Betreff, um die Methode aufzurufen. Hier wird die IQueryable<> verwendet.

Ich habe meine Abfrageklasse geändert, um alle LambdaExpression getrennt zu halten, und diese werden dann getrennt an den QueryTranslator übergeben. Die QT führt die Ausgabe-SQL an den richtigen Stellen zusammen.

Dies ist im Gegensatz zu einem IQueryable<> QueryProvider, der einen Super-Ausdruck analysiert und SQL an den richtigen Stellen basierend auf MethodCallExpression im Ausdruck ausgibt.