2012-05-11 16 views
7

Ich habe eine Methode in einem Webservice, der über Parameter verfügt, mit denen Benutzer entscheiden können, wie sie ihre Ergebnisse sortieren möchten. Dies ist ein List(Of String) mit den Namen der Felder in der Reihenfolge, in der sie sortiert werden sollen.Linq-Abfrage mit mehreren OrderBy-Anweisungen in einer Schleife hinzugefügt

Ich weiß, ich kann in der Regel auf mehrere Spalten bestellen, indem Sie die folgenden Aktionen ausführen in diesem Fall

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

Allerdings wird dies nicht funktionieren, da ich nicht Kette kann die ThenBy Funktion, weil ich die Sortierungen bin Hinzufügen in einer Schleife. Um ThenBy zu verwenden, brauche ich eine IOrderedQueryable Sammlung. Dies ist, wie ich mag es

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 

Dies natürlich funktioniert nicht arbeiten, weil OrderBy jeweils frühere Bestellung ersetzen. Die einzige Lösung, die ich mir vorstellen kann, ist die Reihenfolge der Liste auf einer anderen Variablen zuerst, so habe ich bereits eine IOrderedQueryable Sammlung, aber das scheint nur wie der falsche Ansatz.

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

"SortiertNach jeweils frühere Ordnung ersetzen". Unwahr. OrderBy behält die vorherigen Bestellungen bei ... das bedeutet: es ist eine stabile Nachbestellung. Bedeutet auch: Es verwendet die vorherige Reihenfolge, um Bindungen in der aktuellen Reihenfolge zu brechen. Also: OrderBy (Foo). ThenBy (Balken). ThenBy (Test) ist das gleiche wie OrderBy (Test) .OrderBy (Balken) .OrderBy (Foo) –

Antwort

7

Sie könnten Ihre eigene Erweiterungsmethode OrderByOrThenBy schreiben, der überprüft, ob der Wert bereits ein IOrderedQueryable verwendet ThenBy wenn ja und OrderBy anders. Etwas übel riechend, aber nicht sehr schwer zu machen.

EDIT: C# Probe (ungetestete):

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

Ein C# -Probe wäre in Ordnung, ich kann die Konvertierung selbst machen. –

+0

@FreekBuurman: Vollständig ungetestet, aber sehe meine Bearbeitung ... –

+0

Das sieht aus wie eine nette Lösung, danke! –

Verwandte Themen