29 Oct 2009

Dynamic Linq OrderBy - Sort Field known only at Run-Time

A common issue with my LinqToSql stuff is the need to do an OrderBy on an IQueryable a la:
myQueryable = myQueryable.OrderBy(item => item.mySortField)

However, often you won't know the sort field until runtime, e.g. for a dynamically sortable grid.

One solution is to use the DynamicQueryable library provided by MS. It lets you do string-based dynamic querying like so:
myQueryable = myQueryable.OrderBy(mySortFieldName + " ASC"); // or use DESC if you like it in descending order

However this didn't have an option for using an IComparer to sort the results, and I wanted to use my NaturalSortComparer for natural case sorting. The solution I came up with was this:
myQueryable = myQueryable.OrderBy(item => item.GetReflectedPropertyValue(mySortFieldName ));

Or, actually employing NaturalSortComparer, like this:
myQueryable = myQueryable.OrderBy(item => item.GetReflectedPropertyValue(mySortFieldName ), new NaturalSortComparer<string>());

The solution uses a little helper method called GetReflectedPropertyValue():

public static string GetReflectedPropertyValue(this object subject, string field)
{
object reflectedValue = subject.GetType().GetProperty(field).GetValue(subject, null);
return reflectedValue != null ? reflectedValue.ToString() : "";
}

OK, Reflection is slow (not sure how it compares to building a Lambda Expression tho) but it does the job for my purposes.

3 comments:

  1. Anonymous11:41 am

    Any chance of some help? I use a query to pull back an Enumerable of string values:

    .Select("fieldname").Distinct()

    Then try to use .OrderBy(item=>item.GetReflectedPropertyValue("fieldname"))

    and when it runs I get "Object reference not set to an instance of an object."

    I'm new to all this. Think the problemm is with the name I'm using in the GetReflectedPropertyValue call but not sure what that name should be or if there is even a name at this point?

    ReplyDelete
  2. Obviously "fieldname" needs to actually be the name of a property on whatever you're Select-ing from. Once you've projected the values via a Select, they won't have a "fieldname" property to sort on - they will just be sting literals. So try OrderBy(item => item) instead.

    To be honest I have no clue if you will read this reply because you're Anonymous :) But I suggest that if you have further problems, you create a question on Stack Overflow. You'll get a reply in minutes.

    ReplyDelete
  3. Anonymous12:23 pm

    I did read it :) Yeah I tried item=>item and no joy there either. I'll give stack overflow a try. Thanks for quick response!

    ReplyDelete

Comments are very welcome unless you're a spammer, in which case you should probably kill yourself.

If I helped you out today, you can buy me a beer below. Cheers!