2012-05-11 4 views
7

J'ai une méthode dans un webservice qui a un paramètre avec lequel les utilisateurs peuvent décider comment ils veulent commander leurs résultats. C'est un List(Of String) avec les noms des champs dans l'ordre dans lequel ils veulent les trier.Requête Linq avec plusieurs instructions OrderBy ajoutées dans une boucle

Je sais que je peux normalement commander sur plusieurs colonnes en procédant comme suit

Dim test = Bars.OrderBy(Function(x) x.Foo) _ 
       .ThenBy(Function(x) x.Bar) _ 
       .ThenBy(Function(x) x.Test) 

Cependant, dans ce cas, cela ne fonctionnera pas car je ne peux pas la chaîne la fonction ThenBy parce que j'ajoute les ordres de tri dans une boucle. Pour utiliser ThenBy j'ai besoin d'une collection IOrderedQueryable. Voilà comment je voudrais que cela fonctionne

Dim sortColumns = {"Foo", "Bar", "Test"} 
Dim query = From b in Bars 
For each column in sortColumns 
    Select Case column 
     Case "Foo" 
      query = query.Orderby(Function(x) x.Foo) 
     Case "Bar" 
      query = query.Orderby(Function(x) x.Bar) 
     Case "Test" 
      query = query.Orderby(Function(x) x.Test) 
    End Select 
Next 

Dim result = query.Select(Function(x) x.x).ToList() 
Return result 

Bien sûr, ne fonctionnera pas parce que OrderBy remplacera toute commande précédente. La seule solution à laquelle je peux penser est de commander d'abord la liste sur une autre variable, donc j'ai déjà une collection IOrderedQueryable mais cela semble être la mauvaise approche.

Dim bars As New List(Of Bar) 
Dim sortColumns = {"Foo", "Bar", "Test"} 
Dim query = bars.Select(Function(x) New With {.Temp = 1, .x = x}) _ 
       .OrderBy(Function(x) x.Temp) 

For Each column In sortColumns 
    Select Case column 
     Case "Foo" 
      query = query.ThenBy(Function(x) x.x.Foo) 
     Case "Bar" 
      query = query.ThenBy(Function(x) x.x.Bar) 
     Case "Test" 
      query = query.ThenBy(Function(x) x.x.Test) 
    End Select 
Next 

Dim result = query.Select(Function(x) x.x).ToList() 
Return result  
+0

"OrderBy remplacera toute commande précédente". Faux. OrderBy préserve les commandes précédentes ... c'est-à-dire qu'il s'agit d'une réorganisation stable. Cela signifie aussi: il utilise la commande antérieure pour rompre les liens dans l'ordre actuel. Donc: OrderBy (Foo) .ThenBy (Bar) .ThenBy (Test) est le même que OrderBy (Test) .OrderBy (Bar) .OrderBy (Foo) –

Répondre

7

Vous pouvez écrire votre propre méthode d'extension OrderByOrThenBy qui vérifie si la valeur est déjà un IOrderedQueryable, utilise ThenBy le cas échéant et OrderBy autrement. Légèrement malodorant, mais pas très difficile à faire.

EDIT: C# échantillon (non testé):

public static class QueryableOrdering 
{ 
    public static IOrderedQueryable<TElement> OrderByOrThenBy<TElement, TKey> 
     (this IQueryable<TElement> source, 
     Expression<Func<TElement, TKey>> ordering) 
    { 
     if (source == null) 
     { 
      throw new ArgumentNullException("source"); 
     } 
     if (ordering == null) 
     { 
      throw new ArgumentNullException("ordering"); 
     } 
     var ordered = source as IOrderedQueryable<TElement>; 
     return ordered == null ? source.OrderBy(ordering) 
           : ordered.ThenBy(ordering); 
    } 
} 
+0

Un échantillon C# serait bien, je peux faire la conversion moi-même. –

+0

@FreekBuurman: Complètement non testé, mais voir mon edit ... –

+0

Cela ressemble à une belle solution, merci! –