Building an OrderBy Lambda expression based on child entity's property

c# expression-trees lambda linq

Question

I'm trying to generate a LINQ OrderBy clause using lambda expressions with an input of the column name of an entity as a string (in the "sortOn" variable below).

The code below works fine for a sortOn value like "Code" generating the lambda

p => p.Code

But I would also like to sort on a child entity, where the lambda might be

p => p.Category.Description

So in this instance, I would just like to set sortOn = "Category.Description" and have the correct lamdba expression generated.

Is this possible? Any suggestions about the best way to do this would be welcomed.

This code works fine for the simple case:

var param = Expression.Parameter(typeof (Product), "p");

var sortExpression = Expression.Lambda<Func<Product, object>>(
    Expression.Property(param, sortOn), param);

if (sortAscending ?? true)
{
   products = products.OrderBy(sortExpression);
}
else
{
   products = products.OrderByDescending(sortExpression);
}

The use-case for this problem is displaying a grid of data and being able to sort the data, simply by passing the column name to be sorted on back to the server. I'd like to make the solution generic, but have started using a particular type (Product in the example) for now.

Accepted Answer

This will generate proper lambda expression:

var sortOn = "Category.Description";
var param = Expression.Parameter(typeof(Product), "p");
var parts = sortOn.Split('.');

Expression parent = param;

foreach (var part in parts)
{
    parent = Expression.Property(parent, part);
}

var sortExpression = Expression.Lambda<Func<Product, object>>(parent, param);

Popular Answer

You can use the Dynamic LINQ Query Library to do this easily. Assuming you have an IQueryable<T> implementation of Product, you can easily do:

IQueryable<Product> products = ...;

// Order by dynamically.
products = products.OrderBy("Category.Description");

The blog post has a link to the libary, and you'll have to build/include the project in your solution yourself, but it works very well, and the parsing is very robust. It prevents you from having to write the parsing code yourself; even for something so simple, if the requirements expand, the library has you covered, whereas a homegrown solution does not.

It also has a number of other dynamic operators (Select, Where, etc.) so you can perform other dynamic operations.

There's no magic under the hood, it just parses the strings you pass it and then creates the lambda expressions based on the parsing results.



Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Is this KB legal? Yes, learn why
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Is this KB legal? Yes, learn why