Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Linq query with multiple OrderBy statements added in a loop

I have a method in a webservice that has parameter with which users can decide how they want to order their results. This is a List(Of String) with the names of the fields in the order they want to sort them.

I know I can normally order on multiple columns by doing the following

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

However in this case this won't work since I can't chain the ThenBy function because I'm adding the sorting orders in a loop. To use ThenBy I need an IOrderedQueryable collection. This is how I would want it to work

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

This of course won't work because OrderBy will replace any previous ordering. The only solution I can think of is ordering the list on some other variable first so I already have an IOrderedQueryable collection but this just seems like the wrong approach.

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    
like image 988
Freek Buurman Avatar asked May 11 '12 13:05

Freek Buurman


People also ask

How to use multiple orderby conditions in LINQ?

To use multiple orderby condition in LINQ , one can use the statement like the way shown below. The same can be achieved via Lambda expression with the OrderBy and ThenBy methods like shown below. If the developer wants to sort one of the columns by ascending order and other by descending .

How to sort data in ascending order using LINQ orderby?

The Linq OrderBy method in C# is used to sort the data in ascending order. The most important point that you need to keep in mind is this method is not going to change the data rather it is just changing the order of the data. You can use the OrderBy method on any data type i.e. you can use character, string, decimal, integer, etc.

How to use the orderby keyword in LINQ?

The orderby keyword can be used in LINQ to retrieve the ordered list of records based on the specified field. For example to order the list of movies , one might use the orderby as shown below in the LINQ query How to use Multiple OrderBy Clause in LINQ and Lambda Expression?

How to use the LINQ_orderby operator in Python?

The LINQ_OrderBy operator is mainly used to rearrange the collection of elements in the sequence in ascending order. If we want to make the collection in descending order, use the keyword descending to retrieve the collection in descending order. In the LINQ-OrderBy method, it supports both query and method syntax.


1 Answers

You could write your own extension method OrderByOrThenBy which checks whether the value is already an IOrderedQueryable, uses ThenBy if so and OrderBy otherwise. Slightly smelly, but not terribly hard to do.

EDIT: C# sample (untested):

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);
    }
}
like image 110
Jon Skeet Avatar answered Nov 08 '22 10:11

Jon Skeet