Можно ли сгруппировать набор LINQ в словарь одним запросом? - PullRequest
1 голос
/ 01 марта 2010

Дана таблица позиций заказов ( OrderItems ), которая относится к таблице заказов ( Orders ), которая, в свою очередь, относится к таблице пользователей ( Users *) 1006 *), возможно ли извлечь все OrderItems и сгруппировать их в словарь по OrderId всего одним запросом? то есть. без выполнения итерации для набора результатов OrderItems или выполнения запроса для каждого заказа.

Псевдокод желаемого контроллера

Dictionary<int,IEnumerable<OrderItem>> OrderItems = DataContext.OrderItems.ToDictionary(Key => oi.OrderId, Value => oi.ToList());

Желаемое использование:

IEnumerable<OrderItem> currentOrderItems = OrderItems[123]; // where 123 is OrderId

Текущий метод

В моем контроллере в настоящее время я получаю заказы пользователя и элементы заказа для передачи в представление «Заказы»:

ViewData["Orders"] = (from o in orders
                      where o.UserId equals CurrentUserId
                      orderby o.DateCreated descending)
                     .ToList();

ViewData["OrderItems"] = (from oi in DataContext.OrderItems
                        join o in DataContext.Orders
                        on oi.OrderId equals o.OrderId
                        where o.UserId equals CurrentUserId
                        select oi)
                        .ToList();

Затем, на мой взгляд, я получаю все позиции заказа:

IEnumerable<OrderItem> orderItems = ViewData["OrderItems"] as IEnumerable<OrderItem>;

и используйте LINQ для группировки и отображения позиций заказа каждого заказа:

IEnumerable<OrderItem> currentOrderItems = orderItems.Where(
                                            i => i.OrderId == order.OrderId
                                           );

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

Ответы [ 2 ]

1 голос
/ 02 марта 2010

Решено! С ToLookup (...)

ViewData["OrderItems"] = (from oi in DataContext.OrderItems
                          join o in DataContext.Orders
                          on oi.OrderId equals o.OrderId
                          where o.UserId == UserId
                          select oi).ToLookup(oi => oi.OrderId, oi => oi);

И на мой взгляд:

ILookup<int,OrderItem> orderItems = ViewData["OrderItems"] as ILookup<int,OrderItem>;

foreach (Order order in orders)
{
    DisplayOrder(order);

    // Now display this order's items:
    foreach(OrderItem item in orderItems[order.OrderId])
    {
        DisplayOrderItem(item);
    }
}

Трассировка показывает только один запрос для создания поиска.

Похоже, я привыкла отвечать на свои вопросы ...

0 голосов
/ 01 марта 2010

Я думаю, что вам лучше всего создать метод, который принимает лямбду для ключа и список для вставки в словарь, а затем просто перечисляет список и добавляет его в словарь, используя ключ, указанный в лямбде. Метод может быть методом расширения IDictionary, и давайте назовем его, скажем, AddRangeWithKeyType ()

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