Сортировка с использованием имени свойства как строки

asp.net asp.net-core c# entity-framework-core linq

Вопрос

Я бы хотел, чтобы мой веб-API мог сортировать свой вывод с помощью строкового параметра, такого как этот:

http://myapi.com/api/people?skip=0&take=50&orderBy=lastName&descending=true .

Поскольку у меня также есть поддержка разбивки на страницы (с skip и take ) в моем API, я бы хотел, orderBy параметр orderBy и descending был применен непосредственно к SQL-запросу, так что правильный результат поступает из базы данных.

Однако при выполнении этого кода код может стать очень трудным для управления при попытке сопоставить параметры для orderBy с фактическими свойствами классов, которые я хочу сортировать, просто используя сравнения строк.

Я нашел решение, которое должно работать с LINQ to Entities и, следовательно, также с новым EF7, однако, когда я пытаюсь скомпилировать этот код с использованием нового Core CLR, я получаю следующее сообщение:

Ошибка CS1503 Аргумент 2: невозможно преобразовать из 'System.Linq.Expressions.Expression>' в 'string'

Код из OrderBy<T> решения - метод OrderBy<T> :

public static IOrderedQueryable<T> OrderBy<T>(this IQueryable<T> source, string propertyName)
{
    return source.OrderBy(ToLambda<T>(propertyName));
}

Похоже, что новый Core CLR не поддерживает эту попытку. Есть ли другой способ получить решение для работы с новой средой CLR? Если нет, какие другие альтернативы мне нужно включить для сортировки с использованием EF7, не приводя к бесчисленным операторам if или switch для сравнения входных строк с именами свойств?

Принятый ответ

Решение из вашей ссылки использует «Expression.Convert», который большую часть времени не работает с LINQ to Entities.

Вот рабочий метод расширения:

public static IOrderedQueryable<TSource> OrderBy<TSource>(this IQueryable<TSource> source, string propertyName)
{
    // LAMBDA: x => x.[PropertyName]
    var parameter = Expression.Parameter(typeof(TSource), "x");
    Expression property = Expression.Property(parameter, propertyName);
    var lambda = Expression.Lambda(property, parameter);

    // REFLECTION: source.OrderBy(x => x.Property)
    var orderByMethod = typeof(Queryable).GetMethods().First(x => x.Name == "OrderBy" && x.GetParameters().Length == 2);
    var orderByGeneric = orderByMethod.MakeGenericMethod(typeof(TSource), property.Type);
    var result = orderByGeneric.Invoke(null, new object[] { source, lambda });

    return (IOrderedQueryable<TSource>)result;
}

Отказ от ответственности : Я являюсь владельцем проекта EF + на GitHub.

Вы можете найти другие методы для заказа по имени свойства в моем репозитории: GitHub

  • OrderByDescending
  • ThenBy
  • ThenByDescending
  • AddOrAppendOrderBy
  • AddOrAppendOrderByDescending

EDIT : ответьте на вопрос

Возможно ли сортировать по свойствам навигации, используя что-то вроде этого, например имя свойства «NavigationProperty.PropertyName»,

Да, вы можете разделить строку и цикл, чтобы создать выражение с помощью пути свойств или использовать оценщик реального выражения.

Отказ от ответственности : Я являюсь владельцем проекта Eval-Expressions.NET

Эта библиотека позволяет вам динамически выполнять весь метод LINQ.

См. LINQ Dynamic

var result = list.OrderByDynamic(x => "NavigationProperty.PropertyName");


Related

Лицензировано согласно: CC-BY-SA with attribution
Не связан с Stack Overflow
Является ли этот КБ законным? Да, узнайте, почему
Лицензировано согласно: CC-BY-SA with attribution
Не связан с Stack Overflow
Является ли этот КБ законным? Да, узнайте, почему