Модераторы: gambit
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Сортировка при загрузке связанных данных, Entity Framework 
:(
    Опции темы
PavelVik
Дата 18.11.2009, 16:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 26
Регистрация: 12.5.2008

Репутация: нет
Всего: нет



Здравствуйте!
У меня возникла проблема - как отсортировать записи, которые подгружаются из БД через навигационные свойства?

Есть вот такая БД и связанная с ней модель, в которой имеет место быть отношение Много-ко-Многим:

user posted image

Если мне нужны все записи из основной таблицы, порядок сортировки можно указать в запросе:

Код

var items = (from tb in Context.componentSet
                             orderby tb.cp_name
                             select tb).Take(1000);


Для подгрузки связанных данных использую такой код:

Код

if (!label.components.IsLoaded)
    label.components.Load();


Вопрос в том, как отсортировать эти подгруженные связанные данные?
PM MAIL   Вверх
PavelVik
Дата 18.11.2009, 18:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 26
Регистрация: 12.5.2008

Репутация: нет
Всего: нет



Итак, сам спросил, сам отвечу.

Получилось решить задачу вот так: 

Код

var Comp = label.components.CreateSourceQuery().OrderBy(Order).Take(1000).ToList();


Но теперь другой вопрос - а как сделать сортировку по двум полям? Т.е. допустим у меня есть таблица с полями Name и Order, в программе я выбираю сортировку по полю Order. Как сделать так, чтобы внутри каждого Order выполнялась еще сортировка по полю Name?
PM MAIL   Вверх
KelTron
Дата 18.11.2009, 19:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 745
Регистрация: 8.10.2006
Где: Красноярск

Репутация: 5
Всего: 38



Думаю по аналогии с l2s должно быть:
Код

.OrderBy(Order).ThenBy(...)



--------------------
Тысячами незримых нитей обвивает тебя Закон. Разрубишь одну - преступник. Десять - смертник. Все - Бог.
Эвенгар Салладорский, основатель Школы Тьмы.
PM MAIL   Вверх
PavelVik
Дата 19.11.2009, 09:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 26
Регистрация: 12.5.2008

Репутация: нет
Всего: нет



Да, действительно, вроде разобрался.

Ответ:
Код

var items = Context.componentSet
                    .OrderBy(p => p.cp_box)
                    .ThenBy(p => p.cp_name)
                    .Take(1000)
                    .ToList();


Но теперь новый вопрос появился - а как передавать значение в OrderBy(p => p.cp_box)? В программе предусматривается динамическая сортировка, порядок выбирает пользователь. Что такое "p => p.cp_box" и как это значение подсунуть в запрос? 

Неужели писать что-то типа:

Код

switch(order)
{
    case 0:
        var items = Context.componentSet
                    .OrderBy(p => p.cp_box)
                    .ThenBy(p => p.cp_name)
                    .Take(1000)
                    .ToList();
        break;
    case 1:
        var items2 = 
        ...
}

PM MAIL   Вверх
KelTron
Дата 19.11.2009, 11:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 745
Регистрация: 8.10.2006
Где: Красноярск

Репутация: 5
Всего: 38



Цитата(PavelVik @  19.11.2009,  09:57 Найти цитируемый пост)
Что такое "p => p.cp_box"

Лямбда выражение, в данном случае значит, что каждый элемент p будет отсортирован по полю cp_box.

Как то так:
Код

var items = Context.componentSet.AsQueryable();

switch(order)
{
    case 0:
        items = items.OrderBy(p => p.cp_box0);
        break;
    case 1:
        items = items.OrderBy(p => p.cp_box1);
        break;
    case 2:
        items = items.OrderBy(p => p.cp_box2);
        break;
    ...
}

items = items.ThenBy(p => p.cp_name).Take(1000).ToList();

cp_box0, cp_box1, cp_box2 - твои поля для сортировки.




--------------------
Тысячами незримых нитей обвивает тебя Закон. Разрубишь одну - преступник. Десять - смертник. Все - Бог.
Эвенгар Салладорский, основатель Школы Тьмы.
PM MAIL   Вверх
PavelVik
Дата 19.11.2009, 14:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 26
Регистрация: 12.5.2008

Репутация: нет
Всего: нет



Почему-то так не получается. Мой код: 

Код

            using (dbEntities Context = new dbEntities())
            {
                var items = Context.componentSet.AsQueryable();
                switch (Order)
                {
                    case (1):
                        items = items.OrderBy(p => p.cp_manufacturer);
                        break;
                    case (2):
                        items = items.OrderBy(p => p.cp_box);
                        break;
                    case (3):
                        items = items.OrderBy(p => p.cp_date_create);
                        break;
                    case (4):
                        items = items.OrderBy(p => p.cp_date_update);
                        break;
                    default:
                        break;
                }
                items = items.ThenBy(p => p.cp_name).ToList();
            }


Ошибка: 'System.Linq.IQueryable<components.component>' does not contain a definition for 'ThenBy' and no extension method 'ThenBy' accepting a first argument of type 'System.Linq.IQueryable<components.component>'.

PM MAIL   Вверх
PavelVik
Дата 19.11.2009, 15:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 26
Регистрация: 12.5.2008

Репутация: нет
Всего: нет



Вроде получилось заставить это работать как мне хотелось.
Ниже приведу код, на случай если кому-то понадобится.
Правда, до конца я так и не понял почему оно работает только в таком виде..

Загрузка данных с сортировкой по двум столбцам (причем, при сортировке по дате, первыми идут более новые):
Код

List<component> Items = new List<component>();
using (dbEntities Context = new dbEntities())
{
    var items = Context.componentSet.AsQueryable();
    switch (Order)
    {
        case (1):
            items = items
                .OrderBy(p => p.cp_manufacturer)
                .ThenBy(p => p.cp_name);
            break;
        case (2):
            items = items
                .OrderBy(p => p.cp_box)
                .ThenBy(p => p.cp_name);
            break;
        case (3):
            items = items
                .OrderByDescending(p => p.cp_date_create)
                .ThenBy(p => p.cp_name);
            break;
        case (4):
            items = items
                .OrderByDescending(p => p.cp_date_update)
                .ThenBy(p => p.cp_name);
            break;
        default:
            items = items
                .OrderBy(p => p.cp_name);
            break;
    }
    Items.AddRange(items.ToList());
}
return Items;


А это сортировка при подгрузке связанных данных:
Код

var items = Context.componentSet.AsQueryable();
switch (Order)
{
    case (1):
        items = label.components
            .CreateSourceQuery()
            .OrderBy(p => p.cp_manufacturer)
            .ThenBy(p => p.cp_name);
        break;
    case (2):
        items = label.components
            .CreateSourceQuery()
            .OrderBy(p => p.cp_box)
            .ThenBy(p => p.cp_name);
        break;
    case (3):
        items = label.components
            .CreateSourceQuery()
            .OrderByDescending(p => p.cp_date_create)
            .ThenBy(p => p.cp_name);
        break;
    case (4):
        items = label.components
            .CreateSourceQuery()
            .OrderByDescending(p => p.cp_date_update)
            .ThenBy(p => p.cp_name);
        break;
    default:
        items = label.components
            .CreateSourceQuery()
            .OrderBy(p => p.cp_name);
        break;
}
Items.AddRange(items.ToList());

PM MAIL   Вверх
KelTron
Дата 19.11.2009, 16:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 745
Регистрация: 8.10.2006
Где: Красноярск

Репутация: 5
Всего: 38



На счёт первого, да, видать не получится ThenBy отделить от OrderBy. Дело в том, что ThenBy работает только на IOrderedEnumerable последовательности, которая получается после OrderBy, и компилятору неизвестно, что в свиче такая последовательность может быть получена. 
Во втором примере полагаю вместо label должно быть items. Тогда лучше сократить код:
var items = Context.componentSet.components.CreateSourceQuery().AsQueryable();
Код

switch (Order)
{
    case (1):
        items = items
            .OrderBy(p => p.cp_manufacturer)
            .ThenBy(p => p.cp_name);
        break;
    case (2):
        items = items
            .OrderBy(p => p.cp_box)
            .ThenBy(p => p.cp_name);
        break;
...

В обоих примерах незачем создавать временный список, можно сразу вернуть результат:
Вместо:
Код

Items.AddRange(items.ToList());

Сделать:
Код

return items.ToList();

Context.Dispose() будет вызван в любом случае, т.к. using разворачивается в try{}finally{}.


--------------------
Тысячами незримых нитей обвивает тебя Закон. Разрубишь одну - преступник. Десять - смертник. Все - Бог.
Эвенгар Салладорский, основатель Школы Тьмы.
PM MAIL   Вверх
PavelVik
Дата 23.11.2009, 16:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 26
Регистрация: 12.5.2008

Репутация: нет
Всего: нет



Я снова вернулся со своими вопросами smile

На этот раз меня интересует, как узнать количество записей в таблице, связанной отношением many-many без загрузки содержимого?

Просто для отдельной таблицы я могу использовать следующий код:

Код

var count = Context.componentSet.Count();


Но что делать, если мне нужно узнать сколько записей в связанной таблице?

Сейчас я делаю так:

Код

var label =
        (from lb in Context.labelSet
         where lb.id == guid
         select lb).FirstOrDefault();

label.components.Load();
return (int)label.components.Count();


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

Как обойти данную проблему?
PM MAIL   Вверх
KelTron
Дата 23.11.2009, 17:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 745
Регистрация: 8.10.2006
Где: Красноярск

Репутация: 5
Всего: 38



Может так, код не проверял, нету под рукой такой бд)
Код

var count = Context.labelSet
    .Where(lb => lb.id == guid)
    .SelectMany(lb => lb.components)
    .Count();



--------------------
Тысячами незримых нитей обвивает тебя Закон. Разрубишь одну - преступник. Десять - смертник. Все - Бог.
Эвенгар Салладорский, основатель Школы Тьмы.
PM MAIL   Вверх
PavelVik
Дата 25.11.2009, 11:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 26
Регистрация: 12.5.2008

Репутация: нет
Всего: нет



KelTron, спасибо в очередной раз за помощь!

А не подскажешь, как можно увидеть SQL-запрос, который сформировала модель? Чтобы оценить эффективность.
PM MAIL   Вверх
KelTron
Дата 25.11.2009, 13:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 745
Регистрация: 8.10.2006
Где: Красноярск

Репутация: 5
Всего: 38



Самое простое вывести в консоль:
Код

using (var dc = ...)
{
    dc.Log = Console.Out;
    
    ...тут твой запрос
}

Но можно в лог подсунуть любой TextWriter. А вообще поищи по словам datacontext logging, кучу ссылок выдаёт.

Это всё конечно для l2s, для entity framework может отличаться.



--------------------
Тысячами незримых нитей обвивает тебя Закон. Разрубишь одну - преступник. Десять - смертник. Все - Бог.
Эвенгар Салладорский, основатель Школы Тьмы.
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Прежде чем создать тему, посмотрите сюда:
stab
mr.DUDA
Exception

Используйте теги [code=csharp][/code] для подсветки кода. Используйтe чекбокс "транслит" если у Вас нет русских шрифтов.

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, stab, mr.DUDA, Exception.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Базы данных под .NET | Следующая тема »


 




[ Время генерации скрипта: 0.0512 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.