Linq-to-Entities Динамическая сортировка - PullRequest
18 голосов
/ 30 апреля 2010

Это мой запрос, как я могу использовать строку в качестве параметра orderby?

string sortColumn="Title";

var  items = (from ltem in ctxModel.Items
              where ltem.ItemID == vId
              orderby //something here
              select ltem).Skip(PageSize * PageIndex).Take(PageSize);

UPDATE:
Я не могу просто заказать набор результатов, потому что мне FIRST нужно отсортировать, и только THEN на страницу.

Ответы [ 5 ]

13 голосов
/ 20 марта 2013

Я использую этот помощник:

public static class OrderExt
{
    private static IOrderedQueryable<T> Order<T>(this IQueryable<T> source, string propertyName, SortDirection descending, bool anotherLevel = false)
    {
        var param = Expression.Parameter(typeof(T), string.Empty);
        var property = Expression.PropertyOrField(param, propertyName);
        var sort = Expression.Lambda(property, param);

        var call = Expression.Call(
            typeof (Queryable),
            (!anotherLevel ? "OrderBy" : "ThenBy") +
            (descending == SortDirection.Descending ? "Descending" : string.Empty),
            new[] {typeof (T), property.Type},
            source.Expression,
            Expression.Quote(sort));

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

для вызова помощника, например, сделайте это:

string sort = HttpContext.Current.Request.QueryString["sort"];
var products = _productRepository.OrderBy(sort, SortDirection.Ascending);
8 голосов
/ 01 мая 2010

Вот еще одна альтернатива, EntitySorter . Позволяет немного, что динамический LINQ делает со строками, но оборачивает операцию в объекте, точно так же, как с шаблоном Query Object . Это позволяет как сортировать по строкам, так и по типам безопасных конструкций. Вот несколько примеров:

// Ways of defining an entity sorter
// 1. Using strings:
IEntitySorter<Person> sorter = EntitySorter<Person>
    .OrderBy("Address.City")
    .ThenByDescending("Id");

// 2. Defining a sorter with lambda's
IEntitySorter<Person> sorter = EntitySorter<Person>
    .OrderByDescending(p => p.Name)
    .ThenBy(p => p.Id)
    .ThenByDescending(p => p.Address.City);

// 3. Using a LINQ query
IEntitySorter<Person> sorter =
    from person in EntitySorter<Person>.AsQueryable()
    orderby person.Name descending, person.Address.City
    select person;

// And you can pass a sorter from your presentation layer
// to your business layer, and you business layer may look
// like this:
static Person[] GetAllPersons(IEntitySorter<Person> sorter)
{
    using (var db = ContextFactory.CreateContext())
    {
        IOrderedQueryable<Person> sortedList =
            sorter.Sort(db.Persons);

        return sortedList.ToArray();
    }
}

Вы можете найти код здесь .

6 голосов
/ 01 мая 2010

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

  • Используйте Object Call синтаксис и динамически создавайте дерево выражений запросов. Например ...

См. http://blog.cincura.net/229310-sorting-in-iqueryable-using-string-as-column-name/

Важно учитывать Отложенное выполнение в этом сценарии. Вы можете безопасно построить свой запрос, который возвращает объект IQueryable , а затем выполнить сортировку запроса объекта для этого объекта. Ваш запрос будет выполнен только один раз, когда данные действительно будут доступны.

Приведенная выше запись блога является примером того, как вы можете использовать Expression API для построения и дерева выражений, которое вы можете использовать для OrderBy . Это действительно звучит сложно. Статья MSDN может быть лучшей ссылкой. См. Как: использовать деревья выражений для построения динамических запросов в MSDN.

или

  • Используйте простой маршрут и просто используйте переключатель заголовка для всего запроса.

Например.

ItemType items = default(ItemType);
switch(sortColumn)
{
     case "Title":
     {
           items = ctxModel.Items
                    .Where(i => i.ItemID == vId)
                    .OrderBy( i => i.Title);
     }
     break;
 }
4 голосов
/ 01 мая 2010

Очевидно, что другие намеки на Dynamic Linq недостаточно ясны. Позвольте мне пролить свет ..

Использование Dynamic Linq не обязательно указывает на необходимость зависимости сборки.

Динамический Linq содержится в одном исходном файле, если я не ошибаюсь, который включен в примеры C #, на которые каждый должен был хотя бы когда-нибудь взглянуть за последние 3 года, и может быть легко перенесен в проект и помещен в пространство имен. предотвращать конфликты, тем самым предоставляя услуги по построению выражений, которые могут использоваться везде, где возникает такая необходимость.

Я считаю, что способность безопасно строить выражение из достаточно произвольного string, которое можно легко построить на лету, является лучшим примером «динамического».

Рассмотрим:

    var query = northwind.Products
                         .Where("CategoryID = 3 AND UnitPrice > 3")
                         .OrderBy("SupplierID");
1 голос
/ 30 апреля 2010

Этот запрос выглядит так, как будто вы используете пользовательскую привязку данных и / или ObjectDataSource, независимо от того, есть способ сделать это с помощью метода расширения, который принимает выражение сортировки и динамически добавляет вызов (выражение) OrderBy () к linq запрос. Я задокументировал, как в посте в блоге некоторое время назад, который по совпадению был частью этого ТАКОГО вопроса . Если вам нужно больше, вы можете использовать dynamic linq , который хорошо документирован от scottgu.

РЕДАКТИРОВАТЬ: использование метода расширения будет выглядеть как

string sortColumn="Title";

    var  items = (from ltem in ctxModel.Items
                  where ltem.ItemID == vId
                  select ltem).Skip(PageSize * PageIndex).Take(PageSize).OrderBy(sortColumn);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...