2012-05-11 14 views
7

Ho un metodo in un servizio web che ha parametri con cui gli utenti possono decidere come desiderano ordinare i loro risultati. Questo è un List(Of String) con i nomi dei campi nell'ordine in cui vogliono ordinarli.Query Linq con più istruzioni OrderBy aggiunte in un loop

so di poter normalmente ordinare su più colonne nel modo seguente

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

Tuttavia, in questo caso questo non funzionerà in quanto non riesco a catena la funzione ThenBy perché sto aggiungendo gli ordini di ordinamento in un ciclo. Per utilizzare ThenBy ho bisogno di una collezione IOrderedQueryable. Questo è come vorrei farlo funzionare

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 

Questo ovviamente non funzionerà perché OrderBy sostituirà qualsiasi ordinamento precedente. L'unica soluzione a cui riesco a pensare è ordinare la lista su qualche altra variabile prima, quindi ho già una collezione IOrderedQueryable ma questo sembra l'approccio sbagliato.

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 sostituirà qualsiasi ordinamento precedente". Falso. OrderBy preserva gli ordini precedenti ... significato: è un riordino stabile. Significa anche: usa l'ordinamento precedente per rompere i legami nell'ordine corrente. Quindi: OrderBy (Foo) .ThenBy (Bar) .ThenBy (Test) è lo stesso di OrderBy (Test) .OrderBy (Bar) .OrderBy (Foo) –

risposta

7

Si potrebbe scrivere il proprio metodo di estensione OrderByOrThenBy che verifica se il valore è già un IOrderedQueryable, utilizza ThenBy in caso affermativo e OrderBy altrimenti. Un po 'puzzolente, ma non terribilmente difficile da fare.

EDIT: C# del campione (non testata):

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 campione C# andrebbe bene, posso fare la conversione da solo. –

+0

@FreekBuurman: Completamente non testato, ma vedi la mia modifica ... –

+0

Sembra una buona soluzione, grazie! –