Задать вопрос

Сортировка в LINQ to SQL

Есть задача отобразить… ну для примера товары в разделе интернет магазина.

Используется LINQ to SQL.

Пишу примерно такой код:
List lstGoods = DataContext.Sections.Where(x=>x.id = iMySectionId).First().Goods.Take(iPageSize).ToList();


Проблема в том, что товары нужно упорядочивать. Код преобразовывается:
List lstGoods = DataContext.Sections.Where(x=>x.id = iMySectionId).First().Goods.OrderBy(x=>x.Name).Take(iPageSize).ToList();


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

Получаем примерно такое:
Первый вариант
List lstGoods = null;
if(sSortField == «name»)
{
  if(sSortDirection == «ASC»)
  {
    lstGoods = DataContext.Sections.Where(x=>x.id = iMySectionId).First().Goods.OrderBy(x=>x.Name).Take(iPageSize).ToList();
  }
  else
  {
    lstGoods = DataContext.Sections.Where(x=>x.id = iMySectionId).First().Goods.OrderByDescending(x=>x.Name).Take(iPageSize).ToList();
  }
}

И такое для всех полей. Ужас же! Столько запросов отличающихся только одним параметром. А если полей для сортировки пятнадцать а запрос занимает десять строк? Это же невозможно поддерживать.

Второй вариант
List lstGoods = DataContext.Sections.Where(x=>x.id = iMySectionId).First().Goods.ToList();
if(sSortField == «name»)
{
  if(sSortDirection == «ASC»)
  {
    lstGoods = lstGoods .OrderBy(x=>x.Name).Take(iPageSize);
  }
  else
  {
    lstGoods = lstGoods .OrderByDescending(x=>x.Name).Take(iPageSize);
  }
}


Уже хорошо. Но на сколько я понимаю работу LINQ to SQL, первый запрос (тот что перед первым if), будет скомпилирован в один SQL запрос, выполнен, потом мне вернется List из Good (причем из всех лежащих в этой секции, мы не можем выбрать первые iPageSize товаров, т.к. не известен их порядок), потом уже внутри программы весь этот List будет отсортирован и от него взяты первые iPageSize элементов. Получается разбазаривание вычислительной мощности на сортировку внутри кода. Это SQL сервер сделает лучше и быстрее. И не надо товары не вошедшие на текущую страницу пересылать.

Как правильно решить мою проблему не прибегая к DataContext.ExecuteQuery?
  • Вопрос задан
  • 4536 просмотров
Подписаться 4 Оценить Комментировать
Пригласить эксперта
Ответы на вопрос 4
@KING
Вот рабочий класс, который я уже использовал
http://aonnull.blogspot.com/2010/08/dynamic-sql-like-linq-orderby-extension.html

LINQ запрос выполняется непосредственно на этапе его использования (ToList(), foreach, etc.), а не на этапе формирования.
Ответ написан
Комментировать
aavezel
@aavezel
Веб девелопер
код:

var allGoods = DataContext.Sections.Where(x=>x.id = iMySectionId).First().Goods;
List lstGoods = allGoods.OrderBy(x=>x.Name).OrderByDescending(x=>x.Price).Take(iPageSize).ToList();

выполнит один запрос…
Ответ написан
Комментировать
@antonlustin
как вариант можно воспользоваться рефлекшеном, правда надо будет еще подумать над оптимизацией. рефлекшен штука не быстрая.

List<Person> list = new List<Person>();
list.Add(new Person() { Age = 20, Name="Вася"});
list.Add(new Person() { Age = 21, Name = "Петя" });
list.Add(new Person() { Age = 23, Name = "Коля" });
list.Add(new Person() { Age = 18, Name = "Саша" });

PropertyInfo pi = new Person().GetType().GetProperty("Name");
            
List<Person> sorted = list.OrderBy(p=> pi.GetValue(p, null)).ToList();
Ответ написан
@khaale
            List<Person> list = new List<Person>();
            list.Add(new Person() { Age = 20, Name = "Вася" });
            list.Add(new Person() { Age = 21, Name = "Петя" });
            list.Add(new Person() { Age = 23, Name = "Коля" });
            list.Add(new Person() { Age = 18, Name = "Саша" });

            string propertyName = "Age";

            ParameterExpression parameterExpr = 
                Expression.Parameter(typeof(Person), "person");

            Expression<Func<Person, object>> orderByExpr = 
                Expression.Lambda<Func<Person, object>>(
                    Expression.TypeAs(
                        Expression.Property(
                            parameterExpr, propertyName), typeof(object)), parameterExpr);

            Func<Person, object> orderByFunc = orderByExpr.Compile();

            List<Person> sorted = list.OrderByDescending(p => orderByFunc(p)).ToList();

Попробуйте так. По идее должно работать как в L2O, так и в L2S.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы