2

I'm building a Spec Evaluator which must consider multiple possible OrderBy, as in the next example:

if (spec.Order != null)
{
    var count = spec.Order.Count;

    if (count == 1)
    {
        query = query.OrderBy(spec.Order[0]);
    }
    else if (count == 2)
    {
        query = query.OrderBy(spec.Order[0])
            .ThenBy(spec.Order[1]);
    }
    else if (count == 3)
    {
        query = query.OrderBy(spec.Order[0])
            .ThenBy(spec.Order[1])
            .ThenBy(spec.Order[2]);
    }
    // And so on...
}

Queryis an IQueryable, spec.Order is a list of clauses: List<Expression<Func<T, object>>>.

I know that I can use an OrderBy with all the clauses passed as string. And I guess I can just project all the Order clauses to a new string comma-separated. But that solution doesn't seem clean.

Is there any other way to dynamically generate one new ThenBy for every item of the Order list, above 1?

Erre Efe
  • 15,387
  • 10
  • 45
  • 77

1 Answers1

4

You could use a for loop. Basically loop through all of the Order values, use OrderBy for the first one, and ThenBy for subsequent items. Since you've said that you're using IQueryable, I've modified this to use a temporary IOrderedQueryable<T> variable.

if (spec.Order != null)
{
    var count = spec.Order.Count;

    IOrderedQueryable<T> orderedQuery = null;
    for (int i = 0; i < count; ++i)
    {
        if (i == 0)
        {
            orderedQuery = query.OrderBy(spec.Order[i]);
        }
        else
        {
            orderedQuery = orderedQuery.ThenBy(spec.Order[i]);
        }
    }
    query = orderedQuery ?? query;
}

You could also approach it like this, although I'm not sure how the performance differs between the two methods, if it does at all:

if (spec.Order != null)
{
    var count = spec.Order.Count;

    for (int i = 0; i < count; ++i)
    {
        if (query is IOrderedQueryable<T> orderedQuery)
        {
            query = orderedQuery.ThenBy(spec.Order[i]);
        }
        else
        {
            query = query.OrderBy(spec.Order[i]);
        }
    }
}
ProgrammingLlama
  • 36,677
  • 7
  • 67
  • 86