9
Apr

Sorting in IQueryable using string as column name

Today my UI/ASP.NET guru workmate asked me whether it’s possible to provide sorting methods on queries (in our case Entity Framework) using column name as string instead of expression. Well, I thought, why it shouldn’t.

My first attention got to the MetadataWorkspace. After couple of attempts it became clear that this is not the best way. So I switched my attention to the expression trees. And that was the way. I ended up with this result.

private static IOrderedQueryable<T> OrderingHelper<T>(IQueryable<T> source, string propertyName, bool descending, bool anotherLevel)
{
    ParameterExpression param = Expression.Parameter(typeof(T), string.Empty); // I don't care about some naming
    MemberExpression property = Expression.PropertyOrField(param, propertyName);
    LambdaExpression sort = Expression.Lambda(property, param);

    MethodCallExpression call = Expression.Call(
        typeof(Queryable),
        (!anotherLevel ? "OrderBy" : "ThenBy") + (descending ? "Descending" : string.Empty),
        new[] { typeof(T), property.Type },
        source.Expression,
        Expression.Quote(sort));

    return (IOrderedQueryable<T>)source.Provider.CreateQuery<T>(call);
}

public static IOrderedQueryable<T> OrderBy<T>(this IQueryable<T> source, string propertyName)
{
    return OrderingHelper(source, propertyName, false, false);
}

public static IOrderedQueryable<T> OrderByDescending<T>(this IQueryable<T> source, string propertyName)
{
    return OrderingHelper(source, propertyName, true, false);
}

public static IOrderedQueryable<T> ThenBy<T>(this IOrderedQueryable<T> source, string propertyName)
{
    return OrderingHelper(source, propertyName, false, true);
}

public static IOrderedQueryable<T> ThenByDescending<T>(this IOrderedQueryable<T> source, string propertyName)
{
    return OrderingHelper(source, propertyName, true, true);
}

It’s a set of extension methods with similar signature as the classic ones OrderBy, ThenBy, etc. only taking string parameter instead of expression. This string parameter is name of field in class to be used for sorting. Enjoy.

There's 6 Comments So Far

  • michal
    April 13th, 2009 at 23:17

    Jirko, really nice trick. ;-) Thanks

  • Bas
    October 20th, 2009 at 18:21

    Funny,
    I’ve been looking for a thing like this for ages and eventually, with some help of several tutorials, decided to device something up myself. And now, few days later I come across your code. Typical… hahaha :)

    Here is my code as I came up with it until now. Maybe not as good as yours but it seems to do sort of the same thing.

    private static IQueryable Sort(IQueryable data, string orderBy, string orderDirection)
    {
    var type = typeof(T);
    var property = type.GetProperty(orderBy);
    var parameter = Expression.Parameter(type, string.Empty);
    var propertyAccess = Expression.MakeMemberAccess(parameter, property);
    var orderByExp = Expression.Lambda(propertyAccess, parameter);
    string command = (orderDirection.Equals(“Descending”)) ? “OrderByDescending” : “OrderBy”;
    MethodCallExpression resultExp = Expression.Call(typeof(Queryable), command, new Type[] { type, property.PropertyType }, data.Expression, Expression.Quote(orderByExp));
    return data.Provider.CreateQuery(resultExp).Cast();
    }

  • Bas
    October 20th, 2009 at 18:23

    hmmm the comment box didn’t like my code. Sorry then I cannot post it.
    Yours is better anyway as it is more worked out.
    cheers! keep up the good sniplets

  • deastr
    October 5th, 2010 at 13:37

    Excellent, thank you!

  • 0verlord
    July 13th, 2011 at 22:50

    How cool is this — thanks! It’s exactly what I needed.

Who Linked To This Post?

  1. Dynamic sorting sample with Linq « Michael Sander

Share your thoughts, leave a comment!