2012-06-14 19 views
5

znalazłem następujące pytanie, które można połączyć wiele Expression<Func<T,bool>> wyrażeń:Kombajny OrderBy Expression z których ekspresja

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

Zastanawiam się, czy stosując podobną technikę, jak go o scalanie .OrderBy Expression<Func<Entity, Key>> z .Where Expression<Func<Entity, bool>> w jednym wyrażeniu typu lub dziedziczącym z typu, System.Linq.Expressions.Expression.

Robię naprawdę przycięte klasy stylu QueryProvider do przyjmowania T => T == ... Func za pośrednictwem publicznych metod .Where i .OrderBy. Ma to na celu, że wyrażenie budowane w tej klasie zostanie przekazane do QueryTranslatora w celu utworzenia odpowiedniego kodu SQL.

Kwerendranslator tego stylu, wywołany z QueryProvider, zwykle przyjmuje jeden argument System.Linq.Expressions.Expression jako argument, który następnie tłumaczy na SQL.

Potrafię wykonać i zrozumieć powyższe pytanie dotyczące łączenia dwóch funkcji .Where. Poniższy strony po to szczególnie użyteczne do tego, i śledzone przez każdy z przykładów:

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

Artykuł CodeProject również przydatne:

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

przypadku kombinacji .OrderBy Func z .Where Func jednak oba mają różne ogólne argumenty. W przypadku .Where to jest Func<Entity, bool>, aw przypadku .OrderBy jest to Func<Entity, Key>.

Połączenie tych dwóch wyrażeń na powierzchni nie jest tak proste, jak połączenie dwóch z tymi samymi ogólnymi argumentami.

Wbudowany silnik wytwarzający ekspresję Func (niepewny dokładnego terminu) jest w stanie połączyć .Where Func z .OrderBy Func. Ciekawi mnie, co dzieje się pod maską, gdy te dwa wyrażenia zostają scalone, aby stać się jednym z nich: System.Linq.Expressions.Expression. Czy jest to możliwe, a jeśli tak, to w jaki sposób łączyłbyś Expression<Func<Entity, bool>> z Expression<Func<Entity,Key>> zakładając, że Podmiot jest tego samego typu w każdym Wyrażeniu?

+0

Jak powinno wyglądać wyrażenie wynikowe? – dtb

+0

Powinien być taki sam jak .Where (T => T.Name == "Cooper") OrderBy (T => T.DateOfBirth) – Anthony

+1

Scalenie '.Where (x => warunek1) .Where (x = > condition2) 'to' .Where (x => condition1 && condition) 'ale nie możesz scalić' .Where (warunek x =>) .OrderBy (x => value) 'w tym samym znaczeniu. A zatem, jak powinno wyglądać wyrażenie wynikowe? 'queryable.Where (warunek x =>) .OrderBy (x => wartość)' nie zwraca wyrażenia, zwraca 'IQueryable '. – dtb

Odpowiedz

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

Podoba mi się prostolinijność, ale nie do końca jestem tym, za czym jestem. Nie mam dostępnego źródła, więc w ten sposób nie ma żadnych pytań. – Anthony

0

Wydaje mi się, że tam, gdzie to pytanie było niejednoznaczne, nie można odpowiedzieć.

Próbowałem zbudować jedną super-ekspresję, na przykład w jaki sposób konstruktor wyrażeń IQueryable<> współpracuje z wyrażeniami .Where i .OrderBy wszystko w jednym wyrażeniu.

Jednak bez tematu moja ograniczona znajomość wyrażeń i drzew wyrażeń sugeruje, że nie jest to możliwe.

Aby połączyć wyrażenie .Where z wyrażeniem .OrderBy w jednym wyrażeniu, należy MethodCallExpression, aby oddzielić dwa od siebie LambdaExpression.

Obiekt wymagający wywołania metody musi mieć numer MethodCallExpression. To tutaj zostaje użyty IQueryable<>.

Zmieniono moją klasę Query, tak aby wszystkie numery LambdaExpression były oddzielne, a następnie przesyłane oddzielnie do QueryTranslatora. QT łączy wyjściowy SQL w odpowiednie miejsca.

Jest to przeciwieństwo zapytania QueryProvider o nazwie IQueryable<>, które analizuje jedną super-ekspresję i wyprowadza kod SQL w odpowiednie miejsca na podstawie MethodCallExpression w wyrażeniu.