Share via


How to create Expression Tree for multiple column OrderBy Expression

Question

Monday, May 20, 2013 5:41 PM

I have create an orderby expression for my EF generic Repository as following

               string command = orderByDesc ? "OrderByDescending" : "OrderBy";

                var type = typeof(T);

                var property = type.GetProperty(orderby);

                var parameter = Expression.Parameter(type, "p");

                var propertyAccess = Expression.MakeMemberAccess(parameter, property);

                var orderByExpression = Expression.Lambda(propertyAccess, parameter);

                var resultExpression = Expression.Call(typeof(Queryable), command, new Type[] { type, property.PropertyType },

                                       items.Expression, Expression.Quote(orderByExpression));
                items = items.Provider.CreateQuery<T>(resultExpression);

Now I want to create the Expression with 2 columns for ordering and wasn't able to find out something helpful.

Please help me to create an orderby expression with 2 columns.

Thanks.

All replies (3)

Monday, May 20, 2013 6:36 PM âś…Answered | 1 vote

private static IEnumerable<T> GetSortedData<T>(IQueryable<T> list, string sortColumnName) 
{ 
    var type = typeof(T); 
    var property = type.GetProperty(sortColumnName); 
    var parameter = Expression.Parameter(type, "p"); 
    var propertyAccess = Expression.Property(parameter, property); 
    var orderByExp = Expression.Lambda(propertyAccess, parameter); 
    MethodCallExpression resultExp = Expression.Call(typeof(Queryable), "OrderBy", new[] { type, property.PropertyType }, list.Expression, Expression.Quote(orderByExp)); 
    return (IEnumerable<T>)Expression.Lambda(resultExp).Compile().DynamicInvoke(); 
} 

Mark as answer if this solves your problem. ... Best Regards D. Chatterjee MCA, RERF


Thursday, February 22, 2018 10:16 AM | 1 vote

I'm really late with response but for someone searching for the real solution this is a working one (the actual solution does not take in account the Then By part:

        public static IOrderedQueryable<T> Order<T>(this IQueryable<T> source, string[] propertyNames, SortOrderEnum sortOrder)
        {
            if (propertyNames.Length == 0)
                throw new InvalidOperationException();
            
            var param = Expression.Parameter(typeof(T), string.Empty);
            var property = Expression.PropertyOrField(param, propertyNames[0]);

            var sort = Expression.Lambda(property, param);

            MethodCallExpression orderByCall = Expression.Call(
                typeof(Queryable),
                "OrderBy" + (sortOrder == SortOrderEnum.DESC ? "Descending" : string.Empty),
                new[] { typeof(T), property.Type },
                source.Expression,
                Expression.Quote(sort));

            if(propertyNames.Length > 1)
            {
                for (int i = 1; i < propertyNames.Length; i++)
                {
                    var item = propertyNames[i];
                    param = Expression.Parameter(typeof(T), string.Empty);
                    property = Expression.PropertyOrField(param, item);

                    sort = Expression.Lambda(property, param);

                    orderByCall = Expression.Call(
                        typeof(Queryable),
                        "ThenBy" + (sortOrder == SortOrderEnum.DESC ? "Descending" : string.Empty),
                        new[] { typeof(T), property.Type },
                        orderByCall,
                        Expression.Quote(sort));
                }
            }

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

Usage:

public enum SortOrderEnum
    {
        /// <summary>
        /// The returned list will be ordered in acending order
        /// </summary>
        ASC,
        /// <summary>
        /// The returned list wil lbe orderded in descending order
        /// </summary>
        DESC
    }

var results = source
                .AsQueryable()
                .Order(new string[] { "field1", "field2", "field3" }, SortOrderEnum.ASC);

Antonio Buonaiuto Microsoft Certified Professional MCP - Certification ID 9408020


Thursday, February 22, 2018 10:17 AM

IMHO this is not the answer for "multiple" column sort. It's still valid for single column sort.

Antonio Buonaiuto Microsoft Certified Professional MCP - Certification ID 9408020