Динамический LINQ OrderBy на IEnumerable <T>/ IQueryable <T> - PullRequest
644 голосов
/ 03 сентября 2008

Я нашел пример в VS2008 Примеры для Dynamic LINQ, который позволяет использовать sql-подобную строку (например, OrderBy("Name, Age DESC")) для упорядочения. К сожалению, включенный метод работает только на IQueryable<T>; . Есть ли способ получить эту функцию на IEnumerable<T>?

Ответы [ 19 ]

4 голосов
/ 16 октября 2012

Благодаря Maarten ( Запрос коллекции с использованием объекта PropertyInfo в LINQ ) я получил это решение:

myList.OrderByDescending(x => myPropertyInfo.GetValue(x, null)).ToList();

В моем случае я работал над "ColumnHeaderMouseClick" (WindowsForm), поэтому просто нашел конкретный нажатый столбец и соответствующий ему PropertyInfo:

foreach (PropertyInfo column in (new Process()).GetType().GetProperties())
{
    if (column.Name == dgvProcessList.Columns[e.ColumnIndex].Name)
    {}
}

OR

PropertyInfo column = (new Process()).GetType().GetProperties().Where(x => x.Name == dgvProcessList.Columns[e.ColumnIndex].Name).First();

(убедитесь, что имена столбцов соответствуют свойствам объекта)

Приветствия

4 голосов
/ 03 сентября 2008

Вы можете добавить это:

public static IEnumerable<T> OrderBy( this IEnumerable<T> input, string queryString) {
    //parse the string into property names
    //Use reflection to get and sort by properties
    //something like

    foreach( string propname in queryString.Split(','))
        input.OrderBy( x => GetPropertyValue( x, propname ) );

    // I used Kjetil Watnedal's reflection example
}

Функция GetPropertyValue взята из ответа Кжетил Ватнедал

Вопрос в том, почему? Любая такая сортировка генерирует исключения во время выполнения, а не во время компиляции (как ответ D2VIANT).

Если вы имеете дело с Linq to Sql, а orderby - это дерево выражений, оно все равно будет преобразовано в SQL для выполнения.

4 голосов
/ 13 января 2010

Вот еще кое-что, что я нашел интересным. Если ваш источник - DataTable, вы можете использовать динамическую сортировку без использования Dynamic Linq

DataTable orders = dataSet.Tables["SalesOrderHeader"];
EnumerableRowCollection<DataRow> query = from order in orders.AsEnumerable()
                                         orderby order.Field<DateTime>("OrderDate")
                                         select order;
DataView view = query.AsDataView();
bindingSource1.DataSource = view;

ссылка: http://msdn.microsoft.com/en-us/library/bb669083.aspx (с использованием DataSetExtensions)

Вот еще один способ сделать это, преобразовав его в DataView:

DataTable contacts = dataSet.Tables["Contact"];    
DataView view = contacts.AsDataView();    
view.Sort = "LastName desc, FirstName asc";    
bindingSource1.DataSource = view;
dataGridView1.AutoResizeColumns();
2 голосов
/ 23 ноября 2017

Этот ответ является ответом на комментарии, которым нужен пример решения, предоставленного @ John Sheehan - Runscope

Пожалуйста, предоставьте пример для остальных из нас.

в DAL (уровень доступа к данным),

Версия IEnumerable:

  public  IEnumerable<Order> GetOrders()
    {
      // i use Dapper to return IEnumerable<T> using Query<T>
      //.. do stuff
      return  orders  // IEnumerable<Order>
  }

Версия IQueryable

  public IQueryable<Order> GetOrdersAsQuerable()
    {
        IEnumerable<Order> qry= GetOrders();
        //use the built-in extension method  AsQueryable in  System.Linq namespace
        return qry.AsQueryable();            
    }

Теперь вы можете использовать версию IQueryable для привязки, например, GridView в Asp.net и использовать преимущества для сортировки (вы не можете сортировать, используя версию IEnumerable)

Я использовал Dapper в качестве ORM и собрал версию IQueryable, а так легко использовал сортировку в GridView в asp.net.

2 голосов
/ 16 марта 2009

Альтернативное решение использует следующий класс / интерфейс. Это не совсем динамично, но работает.

public interface IID
{
    int ID
    {
        get; set;
    }
}

public static class Utils
{
    public static int GetID<T>(ObjectQuery<T> items) where T:EntityObject, IID
    {
        if (items.Count() == 0) return 1;
        return items.OrderByDescending(u => u.ID).FirstOrDefault().ID + 1;
    }
}
1 голос
/ 10 марта 2018

Первая установка Dynamic Инструменты -> Диспетчер пакетов NuGet -> Консоль диспетчера пакетов

install-package System.Linq.Dynamic

Добавить Пространство имен using System.Linq.Dynamic;

Теперь вы можете использовать OrderBy("Name, Age DESC")

0 голосов
/ 25 декабря 2018

Использовать динамический linq

просто добавьте using System.Linq.Dynamic;

И используйте это, чтобы упорядочить все столбцы:

string sortTypeStr = "ASC"; // or DESC
string SortColumnName = "Age"; // Your column name
query = query.OrderBy($"{SortColumnName} {sortTypeStr}");
0 голосов
/ 16 мая 2016
var result1 = lst.OrderBy(a=>a.Name);// for ascending order. 
 var result1 = lst.OrderByDescending(a=>a.Name);// for desc order. 
0 голосов
/ 05 августа 2013

Преобразование списка в IEnumerable или Iquerable, добавление с использованием пространства имен System.LINQ.Dynamic, после чего вы можете указать имена свойств в строке, разделенной запятыми, в метод OrderBy, который по умолчанию поставляется из System.LINQ.Dynamic.

...