Is there a way to order by an IQueryable with a different amount of ordering

For example, I want to try something like this. The sorting par might have none, 1 or several sorting columns by different order. But I can't use the ThenBy method as it's only available after an OrderBy. The code below will keep resetting the order to the last item in the sorting list. I don't want to change the method signature either. Help would be greatly appreciated, thanks.

public IQueryable<Person> FilterList(string forename, List<Sorting> sorting)
{
    IQueryable<Person> query = dc.Set<Person>();

    if(!string.IsNullOrEmpty(forename)){
        query = query.Where(w=>w.Forename.Contains(forename));

    foreach(var sort in sorting)
    {
        switch(sort.By)
        {
            case "asc":
               switch(sort.Sort)
               {
                   case "forename":
                       query = query.OrderBy(o=>o.Forename);
                       break;

                   case "surname":
                       query = query.OrderBy(o=>o.Surname);
                       break;
               }
               break;

            case "desc":
               switch(sort.Sort)
               {
                   case "forename":
                       query = query.OrderByDescending(o=>o.Forename);
                       break;

                   case "surname":
                       query = query.OrderByDescending(o=>o.Surname);
                       break;
               }
               break;
        }
    }

    return query;
}

public class Sorting
{
    public string Sort{get;set;}
    public string By{get;set;}
}
Jon Skeet
people
quotationmark

AgentFire's answer is effectively appropriate, but a bit long-winded to special-case in each situation. I'd add an extension method:

EDIT: Apparently, the code below doesn't correctly determine whether the query is already ordered; even the unordered version implements IOrderedQueryable<T>, apparently. Using source.Expression.Type to check for IOrderedQueryable<T> apparently works, but I've left this code here as the more logical approach - and as this "fix" sounds more brittle than I'd like for an answer with my name on it :)

public static IOrderedQueryable<T> AddOrdering<T, TKey>(
    this IQueryable<T> source,
    Expression<Func<T, TKey>> keySelector,
    bool descending)
{
    IOrderedQueryable<T> ordered = source as IOrderedQueryable<T>;
    // If it's not ordered yet, use OrderBy/OrderByDescending.
    if (ordered == null)
    {
        return descending ? source.OrderByDescending(keySelector)
                          : source.OrderBy(keySelector);
    }
    // Already ordered, so use ThenBy/ThenByDescending
    return descending ? ordered.ThenByDescending(keySelector)
                      : ordered.ThenBy(keySelector);
}

Then your calling code becomes:

foreach(var sort in sorting)
{
    bool descending = sort.By == "desc";
    switch (sort.Sort)
    {
        case "forename":
            query = query.AddOrdering(o => o.Forename, descending);
            break;
        case "surname":
            query = query.AddOrdering(o => o.Surname, descending);
            break;
    }
}

This way each additional sort option only adds a tiny code overhead.

people

See more on this question at Stackoverflow