Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dynamically Sort by lambda expression

I m doing sorting in my application as shown below .

public IQueryable<Users> SelectAll(string sSortExpression, string sSortOrder)
{
    if (sSortOrder == "asc")
    {
        switch (sSortExpression)
        {
            case "FirstName":
                return UsersRepository.Entities.OrderBy(x => x.FirstName);
            case "LastName":
                return UsersRepository.Entities.OrderBy(x => x.LastName);
            default:
                return UsersRepository.Entities.OrderBy(x => x.Id);
        }
    }
    else
    {
        switch (sSortExpression)
        {
            case "FirstName":
                return UsersRepository.Entities.OrderByDescending(x => x.FirstName);
            case "LastName":
                return UsersRepository.Entities.OrderByDescending(x => x.LastName);
            default:
                return UsersRepository.Entities.OrderByDescending(x => x.UserName);
        }
    }
}

Its fine now , but I have to sort on all fields in Users table (Around 30 fields ) . Then the method will be very big

I tried using reflections like this

public IQueryable<Users> SelectAll(string sSortExpression, string sSortOrder)
{
    var _property = UsersRepository.GetType().GetProperties().Where(a => a.Name == sSortExpression);
    if (sSortOrder == "asc")
    {
        return UsersRepository.Entities.OrderBy(x => _property);
    }
    else
    {
        return UsersRepository.Entities.OrderByDescending(x => _property);
    }
}

But faild.

Is there any better way to do this ? Thanks in advance

like image 913
TheCoder Avatar asked Jun 16 '26 14:06

TheCoder


1 Answers

The easiest way to go: change your method to accept Expression instead of string:

public IQueryable<Users> SelectAll<TProp>(Expression<Func<Users, TProp>> selector, string sSortOrder)
{
    if (sSortOrder == "asc")
    {
        return UsersRepository.Entities.OrderBy(selector);
    }
    else
    {
        return UsersRepository.Entities.OrderByDescending(selector);
    }
}

You can call it as:

SelectAll(x => x.LastName, "asc");

Or if you really need it to be string, you have to generate Expression Tree using System.Linq.Expressions.Expression class method:

public IQueryable<Users> SelectAll<TProp>(string sSortExpression, string sSortOrder)
{
    var param = Expression.Parameter(typeof(Users));
    var propExpression = Expression.Lambda<Func<Users, TProp>>(Expression.Property(param, sSortExpression), param);

    if (sSortOrder == "asc")
    {
        return UsersRepository.Entities.OrderBy(propExpression);
    }
    else
    {
        return UsersRepository.Entities.OrderByDescending(propExpression);
    }
}

But it will require to specify generic type parameter on SelectAll call:

var results = SelectAll<int>("Id", "asc");
like image 200
MarcinJuraszek Avatar answered Jun 19 '26 04:06

MarcinJuraszek