HolloW
HolloW

Reputation: 730

LINQ - Dynamic expression to OrderBy

I have a little issue, I'll try to explain this in detail.

Over my system I have a Generic Repository working with EF 4.1. Everything works fantastic, but I have a problem in a certain situation I would need to do dynamic orderBy over some querys.

I recieve by parameter an "string" that represent the field on my class, to do the orderBy (like "id" or "description")

Some portion of code:

        public class SomeClass
        {
            public int id { get; set; }
            public string description { get; set; }
        }

        // First we define the parameter that we are going to use
        // in our OrderBy clause. This is the same as "(parameter =>"
        // in the example above.
        var param = Expression.Parameter(typeof(SomeClass), "parameter");

        // Now we'll make our lambda function that returns the
        // request.SortingName property by it's name.
        var expression = Expression.Lambda<Func<SomeClass, int>>(Expression.Property(param, request.SortingName), param);

Well, this code works if the "request.SortingName" is type "int" (id) , but if I want to make the orderBy by "string" (description) or another type this code doesn't work.

I changed the expression to using "object":

        var expression = Expression.Lambda<Func<SomeClass, object>>(Expression.Property(param, request.SortingName), param);

But when I run the code, the compiler throws the next exception: Expression of type 'System.Int32' cannot be used for return type 'System.Object'

In case the property is string type, the exception is Expression of type 'System.String' cannot be used for return type 'System.Object'

In other words the code doesn't work with "object" type.

Anyone knows how can I figure this out?

Thanks for your time.

Upvotes: 3

Views: 6304

Answers (1)

Rob
Rob

Reputation: 10248

Here's how I do dynamic sort and paginate using EF4 and some generic methods I've created in my standard dev library. The important thing is the second bit of code which you use to create the Lambda expression for the SortBy method.

public enum SqlOrderByDirecton
{
    ASC,
    DESC
}

 //Derive Lambda Expression from string

 string sortByKey = "BusinessId";
 string value = "DESC";

 var p = Expression.Parameter(typeof(T));

 this.SortBy = Expression.Lambda<Func<T, dynamic>>(Expression.TypeAs(Expression.Property(p, sortByKey), typeof(object)), p).Compile();

 this.SortOrder = (DevCore.SqlOrderByDirecton)Enum.Parse(typeof(DevCore.SqlOrderByDirecton), value, true);

public static List<T> SortAndPaginate<T>(IEnumerable<T> query,
                                             Func<T, object> sortBy,
                                             SqlOrderByDirecton sortOrder,
                                             int rowLimit,
                                             int startRecord,
                                             out int recordCount)
    {
        recordCount = query.Count();

        List<T> list = new List<T>();

        if (sortOrder == SqlOrderByDirecton.ASC)
        {
            list = query.OrderBy(sortBy).Skip(startRecord).Take(rowLimit).ToList();
        }
        else
        {
            list = query.OrderByDescending(sortBy).Skip(startRecord).Take(rowLimit).ToList();
        }

        return list;
    }

Upvotes: 8

Related Questions