How to construct Order By Expression dynamically in Entity Framework?

前端 未结 2 422
盖世英雄少女心
盖世英雄少女心 2020-11-30 05:39

I used the following methods to construct Order By Expression. Original Source

It is really slick. The downside is it only works if Property is

相关标签:
2条回答
  • 2020-11-30 06:33

    I have, IMHO, a simpler solution:

    public static IOrderedQueryable<TSource> Sort<TSource>(this IQueryable<TSource> source, bool ascending , string sortingProperty)
    {
        if (ascending)
            return source.OrderBy(item => item.GetReflectedPropertyValue(sortingProperty));
        else
            return source.OrderByDescending(item => item.GetReflectedPropertyValue(sortingProperty));
    }
    
    private static object GetReflectedPropertyValue(this object subject, string field)
    {
        return subject.GetType().GetProperty(field).GetValue(subject, null);
    }
    

    The usage is:

    myQueryableCollection.Sort(ascending: true, "Name")
    

    Of course, the PropertyExist() helper is a great addition...

    0 讨论(0)
  • 2020-11-30 06:39

    I found a solution with the help of Jon Skeet's old answer.

    public static class QueryHelper
    {
        private static readonly MethodInfo OrderByMethod =
            typeof (Queryable).GetMethods().Single(method => 
            method.Name == "OrderBy" && method.GetParameters().Length == 2);
    
        private static readonly MethodInfo OrderByDescendingMethod =
            typeof (Queryable).GetMethods().Single(method => 
            method.Name == "OrderByDescending" && method.GetParameters().Length == 2);
    
        public static bool PropertyExists<T>(this IQueryable<T> source, string propertyName)
        {
            return typeof(T).GetProperty(propertyName, BindingFlags.IgnoreCase |
                BindingFlags.Public | BindingFlags.Instance) != null;
        }
    
        public static IQueryable<T> OrderByProperty<T>(
           this IQueryable<T> source, string propertyName)
        {
            if (typeof (T).GetProperty(propertyName, BindingFlags.IgnoreCase | 
                BindingFlags.Public | BindingFlags.Instance) == null)
            {
                return null;
            }
            ParameterExpression paramterExpression = Expression.Parameter(typeof (T));
            Expression orderByProperty = Expression.Property(paramterExpression, propertyName);
            LambdaExpression lambda = Expression.Lambda(orderByProperty, paramterExpression);
            MethodInfo genericMethod = 
              OrderByMethod.MakeGenericMethod(typeof (T), orderByProperty.Type);
            object ret = genericMethod.Invoke(null, new object[] {source, lambda});
            return (IQueryable<T>) ret;
        }
    
        public static IQueryable<T> OrderByPropertyDescending<T>(
            this IQueryable<T> source, string propertyName)
        {
            if (typeof (T).GetProperty(propertyName, BindingFlags.IgnoreCase | 
                BindingFlags.Public | BindingFlags.Instance) == null)
            {
                return null;
            }
            ParameterExpression paramterExpression = Expression.Parameter(typeof (T));
            Expression orderByProperty = Expression.Property(paramterExpression, propertyName);
            LambdaExpression lambda = Expression.Lambda(orderByProperty, paramterExpression);
            MethodInfo genericMethod = 
              OrderByDescendingMethod.MakeGenericMethod(typeof (T), orderByProperty.Type);
            object ret = genericMethod.Invoke(null, new object[] {source, lambda});
            return (IQueryable<T>) ret;
        }
    }
    

    Usage

    string orderBy = "Name";
    if (query.PropertyExists(orderBy))
    {
       query = query.OrderByProperty(orderBy);
       - OR - 
       query = query.OrderByPropertyDescending(orderBy);
    }
    
    0 讨论(0)
提交回复
热议问题