Как условно столбец в LINQ OrderByDescending для OrderBy в С#?

Как условно отсортировать столбец с помощью предложения LINQ OrderBy.

ex- У меня есть свойство Filter.OrderBy и Filter.Order . В OrderBy может быть много ex> Name, Address, City и т. д., а Order будет по возрастанию или по убыванию, но я не уверен, как сортировать его с условными столбцами

Пожалуйста, найдите приведенный ниже код для справки -

IQueryable<Filter> query;

PropertyInfo prop = typeof(Filter).GetProperty(Filter.OrderBy);  

if (Filter.Order ==" Ascending"){
  query = query.OrderBy ( x = > prop.GetValue(x,null));
}
else if (Filter.Order ==" Descending"){
  query = query.OrderByDescending ( x = > prop.GetValue(x,null));
}

Но запрос не работает. Я не уверен, в чем проблема. Я вижу свойство prop с использованием отражения, но выражение prop.GetValue не работает.

Пожалуйста помоги мне с этим


person Rahul Sharma    schedule 26.03.2020    source источник
comment
Какую ошибку вы получаете?   -  person dcg    schedule 26.03.2020
comment
Запрос @dcg не может найти сортировку с помощью столбца query.OrderBy, кажется, я не могу динамически изменить свойство ex - x => x.Address и т. д.   -  person Rahul Sharma    schedule 26.03.2020
comment
Значит query.OrderBy(x => x.Address) не работает?   -  person RoadRunner    schedule 26.03.2020
comment
@RoadRunner это работает, но мне нужно динамически изменить столбец, как это может быть x =›x.Address или x.City или x.State . Итак, я не хочу жестко кодировать или создавать несколько условий   -  person Rahul Sharma    schedule 26.03.2020
comment
Отвечает ли это на ваш вопрос? c# использует строковый параметр, чтобы определить, какое свойство фильтровать в списке объектов — хотя это предложение Where, его должно быть легко адаптировать к OrderBy   -  person phuzi    schedule 26.03.2020
comment
Кстати, вы сравниваете с " Ascending" и " Descending" (с начальным пробелом), верно? В противном случае вы никогда не будете составлять запрос OrderBy.   -  person dcg    schedule 26.03.2020


Ответы (4)


Вы можете использовать библиотеку System.Linq.Dynamic.Core, которая поддерживает динамические запросы. , выбор и заказ.

Пример кода:

var q = new List<Person>
{
    new Person{Name = "C", Age = 30 },
    new Person{Name = "A", Age = 7 },
    new Person{Name = "B", Age = 5 }
}.AsQueryable();

var x1 = q.OrderBy("Name asc");

var a1 = q.OrderBy("Age desc");

Полный рабочий пример см. в разделе dotnetfiddle.

person Stef Heyenrath    schedule 28.03.2020
comment
Это решение сработало для меня, и его очень легко реализовать, спасибо @Stef Heyenrath. - person Rahul Sharma; 03.04.2020

Я создал этот образец, возможно, он может вам помочь

IEnumerable<Person> q = new List<Person>
{
    new Person{Name = "C", Age = 3 },
    new Person{Name = "A", Age = 7 },
    new Person{Name = "B", Age = 5 }
};
var props = new[] { "Name", "Age" };
var orders = new[] { "Ascending", "Descending" };

foreach (var prop in props)
{
    var property = typeof(Person).GetProperty(prop);
    foreach (var order in orders)
    {
        IEnumerable<Person> q2 = null;
        if (order == "Ascending")
        { q2 = q.OrderBy(p => property.GetValue(p)); }
        else
        { q2 = q.OrderByDescending(p => property.GetValue(p)); }

        Console.WriteLine("Property: {0}, Order: {1}", prop, order);
        foreach (var p in q2)
        {
            Console.WriteLine("Name: {0}, Age: {1}", p.Name, p.Age);
        }
        Console.WriteLine();
    }
}

Выход:

Property: Name, Order: Ascending
Name: A, Age: 7
Name: B, Age: 5
Name: C, Age: 3

Property: Name, Order: Descending
Name: C, Age: 3
Name: B, Age: 5
Name: A, Age: 7

Property: Age, Order: Ascending
Name: C, Age: 3
Name: B, Age: 5
Name: A, Age: 7

Property: Age, Order: Descending
Name: A, Age: 7
Name: B, Age: 5
Name: C, Age: 3
person dcg    schedule 26.03.2020

установите свойства в качестве параметров. Пример:

var param = "Address";    
var propertyInfo = typeof(Filter).GetProperty(param);    
var orderByAddress = items.OrderBy(x => propertyInfo.GetValue(x, null));
person amine_mouhib    schedule 26.03.2020

public static class LinqUtils
    {
        /// <summary>
        /// Orders the by.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="source">The source.</param>
        /// <param name="propertyName">Name of the property.</param>
        /// <param name="direction">The direction.</param>
        /// <returns></returns>
        public static IOrderedMongoQueryable<T> OrderBy<T>(this IMongoQueryable<T> source, string propertyName, OrderDirection direction)
        {
            switch (direction)
            {
                case OrderDirection.ASC:
                    return source.OrderBy(ToLambda<T>(propertyName));

                case OrderDirection.DESC:
                    return source.OrderByDescending(ToLambda<T>(propertyName));

                default:
                    return source.OrderBy(ToLambda<T>(propertyName));
            }

        }

        /// <summary>
        /// Orders the by.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="source">The source.</param>
        /// <param name="propertyName">Name of the property.</param>
        /// <param name="direction">The direction.</param>
        /// <returns></returns>
        public static IOrderedMongoQueryable<T> OrderBy<T>(this IMongoQueryable<T> source, string propertyName, int direction)
        {
            var dir = (OrderDirection)direction;

            switch (dir)
            {
                case OrderDirection.ASC:
                    return source.OrderBy(ToLambda<T>(propertyName));

                case OrderDirection.DESC:
                    return source.OrderByDescending(ToLambda<T>(propertyName));

                default:
                    return source.OrderBy(ToLambda<T>(propertyName));
            }

        }


        /// <summary>
        /// Orders the by.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="source">The source.</param>
        /// <param name="propertyName">Name of the property.</param>
        /// <returns></returns>
        public static IOrderedMongoQueryable<T> OrderBy<T>(this IMongoQueryable<T> source, string propertyName)
        {
            return source.OrderBy(ToLambda<T>(propertyName));
        }

        /// <summary>
        /// Orders the by descending.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="source">The source.</param>
        /// <param name="propertyName">Name of the property.</param>
        /// <returns></returns>
        public static IOrderedMongoQueryable<T> OrderByDescending<T>(this IMongoQueryable<T> source, string propertyName)
        {
            return source.OrderByDescending(ToLambda<T>(propertyName));
        }

        /// <summary>
        /// Wheres the specified property name.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="source">The source.</param>
        /// <param name="propertyName">Name of the property.</param>
        /// <param name="stringToSource">The string to source.</param>
        /// <returns></returns>
        public static IMongoQueryable<T> Where<T>(this IMongoQueryable<T> source, string propertyName, string stringToSource)
        {
            return source.Where(ToLambdaWhere<T>(propertyName, stringToSource));
        }


        /// <summary>
        /// Wheres the text.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="query">The query.</param>
        /// <param name="field">The field.</param>
        /// <param name="search">The search.</param>
        /// <returns></returns>
        public static IMongoQueryable<T> WhereText<T>(this IMongoQueryable<T> query, Expression<Func<T, object>> field, string search)
        {

            search = Regex.Escape(search);
            var filter = Builders<T>.Filter.Text(search);
            var member = HelpersLinq.PropertyName<T>(field);

            var regexFilter = string.Format("^{0}.*", search);
            var filterRegex = Builders<T>.Filter.Regex(member, BsonRegularExpression.Create(new Regex(regexFilter, RegexOptions.IgnoreCase)));

            return query.Where(_ => filter.Inject() && filterRegex.Inject());
        }

        /// <summary>
        /// Converts to lambda.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="propertyName">Name of the property.</param>
        /// <returns></returns>
        private static Expression<Func<T, object>> ToLambda<T>(string propertyName)
        {
            var parameter = Expression.Parameter(typeof(T));
            var property = Expression.Property(parameter, propertyName);
            var propAsObject = Expression.Convert(property, typeof(object));

            return Expression.Lambda<Func<T, object>>(propAsObject, parameter);
        }

        /// <summary>
        /// Converts to lambdawhere.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="propertyName">Name of the property.</param>
        /// <param name="stringToSearch">The string to search.</param>
        /// <returns></returns>
        private static Expression<Func<T, bool>> ToLambdaWhere<T>(string propertyName, string stringToSearch)
        {
            //var parameter = Expression.Parameter(typeof(T));

            // Create a parameter to use for both of the expression bodies.
            var parameter = Expression.Parameter(typeof(T), "x");
            // Invoke each expression with the new parameter, and combine the expression bodies with OR.
            var predicate = Expression.Lambda<Func<T, bool>>(Expression.Call(Expression.PropertyOrField(parameter, propertyName), "Contains", null, Expression.Constant(stringToSearch)), parameter);

            return predicate;
        }
    }


    public static class HelpersLinq
    {
        public static string PropertyName<T>(Expression<Func<T, object>> expression)
        {
            var member = expression.Body as MemberExpression;
            if (member != null && member.Member is PropertyInfo)
                return member.Member.Name;

            throw new ArgumentException("Expression is not a Property", "expression");
        }
    }

public enum OrderDirection
{
    ASC = 1,
    DESC
}

Таким образом, вы можете использовать его как:

 initialQuery.OrderBy("Name", OrderDirection.ASC)

Надеюсь, это поможет вам!

person federico scamuzzi    schedule 26.03.2020