【问题标题】:Is it possible to group a LINQ set into a dictionary with one query?是否可以通过一个查询将 LINQ 集分组到字典中?
【发布时间】:2010-03-01 19:25:52
【问题描述】:

给定与订单表 (Orders) 相关的订单项目表 (OrderItems),而订单表又与用户表 (用户),是否可以通过一个查询检索所有 OrderItems 并按 OrderId 将它们分组到字典中? IE。无需对 OrderItems 结果集执行迭代或对每个订单执行查询。

所需的控制器伪代码

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

所需用途:

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

当前方法

在我的控制器中,我目前检索用户的订单和订单商品以传递给 Orders 视图:

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
                                           );

这是相当有效的,因为只有两个查询被传递到数据库并且在视图中完成了一些处理。但理想情况下,这应该在控制器中完成。

【问题讨论】:

    标签: asp.net-mvc linq-to-sql dictionary grouping


    【解决方案1】:

    解决了!使用 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);
        }
    }
    

    跟踪仅显示一个用于创建查找的查询。

    看来我正在养成回答自己问题的习惯...

    【讨论】:

      【解决方案2】:

      我认为您最好的选择是创建一个方法,该方法接受一个 lambda 作为键和一个要插入字典的列表,然后简单地枚举该列表并使用 lambda 中提供的键添加到字典中。该方法可以是 IDictionary 的扩展方法,我们称之为 AddRangeWithKeyType()

      【讨论】:

      • 我是 lambda 编程新手。您能否提供一个示例并解释它与使用 LINQ .Where(...) 子句简单地迭代订单项结果集有何不同?
      • 没关系,用 .ToLookup(...); 解决谢谢你的回答。
      猜你喜欢
      • 1970-01-01
      • 2022-12-15
      • 1970-01-01
      • 1970-01-01
      • 2019-08-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多