【问题标题】:C# join items which are the same with lambda expressionC# join 与 lambda 表达式相同的项
【发布时间】:2017-10-03 03:11:57
【问题描述】:

使用以下代码,我将如何将项目连接在一起。

var shippedItems = _orderService.GetOrderById(shipment.OrderId).Shipments
    .Where(x => x.ShippedDateUtc != null && x.OrderId == shipment.OrderId)
    .Select(x => x.ShipmentItems)
    .ToList();

因此,订单 ID 可能有两批或多批货件。 每批货物可能包含相同的物品。

需要向正确的方向轻推

试过

var shippedItems = _orderService.GetOrderById(shipment.OrderId).Shipments
    .Where(x => x.ShippedDateUtc != null && x.OrderId == shipment.OrderId)
    .Select(x => x.ShipmentItems.Join(x.ShipmentItems
        .Where(y => y.ShipmentId == shipment.Id)))
    .ToList();

var shippedItems = _orderService.GetOrderById(shipment.OrderId).Shipments
    .Where(x => x.ShippedDateUtc != null && x.OrderId == shipment.OrderId)
    .Select(x => x.ShipmentItems.GroupBy(y => y.Id))
    .ToList();

var shippedItems = _orderService.GetOrderById(shipment.OrderId).Shipments
    .Where(x => x.ShippedDateUtc != null && x.OrderId == shipment.OrderId)
    .Select(x => x.ShipmentItems.Distinct())
    .ToList();

这是我用于输出项目的代码:

foreach (var shipmentItem in shippedItems)
{
    System.Diagnostics.Debug.WriteLine("item = " + shipmentItem);
    System.Diagnostics.Debug.WriteLine("item = " + shipmentItem.OrderItemId);
}

上面的输出产生:

shippedItemsList 计数 = 9 项 = System.Data.Entity.DynamicProxies.ShipmentItem_18BEAAFA747B42988EC4CB25D967298CC6736AF528389FC98E81143F7D629631 项目 = 356077

item = System.Data.Entity.DynamicProxies.ShipmentItem_18BEAAFA747B42988EC4CB25D967298CC6736AF528389FC98E81143F7D629631 项目 = 356078

item = System.Data.Entity.DynamicProxies.ShipmentItem_18BEAAFA747B42988EC4CB25D967298CC6736AF528389FC98E81143F7D629631 项目 = 356079

item = System.Data.Entity.DynamicProxies.ShipmentItem_18BEAAFA747B42988EC4CB25D967298CC6736AF528389FC98E81143F7D629631 项目 = 356077

item = System.Data.Entity.DynamicProxies.ShipmentItem_18BEAAFA747B42988EC4CB25D967298CC6736AF528389FC98E81143F7D629631 项目 = 356078

项目 = System.Data.Entity.DynamicProxies.ShipmentItem_18BEAAFA747B42988EC4CB25D967298CC6736AF528389FC98E81143F7D629631 项目 = 356079

项目 = System.Data.Entity.DynamicProxies.ShipmentItem_18BEAAFA747B42988EC4CB25D967298CC6736AF528389FC98E81143F7D629631 项目 = 356077

item = System.Data.Entity.DynamicProxies.ShipmentItem_18BEAAFA747B42988EC4CB25D967298CC6736AF528389FC98E81143F7D629631 项目 = 356079

item = System.Data.Entity.DynamicProxies.ShipmentItem_18BEAAFA747B42988EC4CB25D967298CC6736AF528389FC98E81143F7D629631 项目 = 356080

所以例外的输出应该是:

shippedItemsList 计数 = 4 项目 = System.Data.Entity.DynamicProxies.ShipmentItem_18BEAAFA747B42988EC4CB25D967298CC6736AF528389FC98E81143F7D629631 项目 = 356077

item = System.Data.Entity.DynamicProxies.ShipmentItem_18BEAAFA747B42988EC4CB25D967298CC6736AF528389FC98E81143F7D629631 项目 = 356079

item = System.Data.Entity.DynamicProxies.ShipmentItem_18BEAAFA747B42988EC4CB25D967298CC6736AF528389FC98E81143F7D629631 项目 = 356078

item = System.Data.Entity.DynamicProxies.ShipmentItem_18BEAAFA747B42988EC4CB25D967298CC6736AF528389FC98E81143F7D629631 项目 = 356080

以上输出来自使用var shippedItems = _orderService.GetOrderById(shipment.OrderId).Shipments.Where(x => x.ShippedDateUtc != null && x.OrderId == shipment.OrderId).SelectMany(x => x.ShipmentItems).ToList();

注意:当我将其悬停在 Visual Studio 中时,发货项目为 ICollection<ShipmentItem> Shipment.ShipmentItems

更新的场景:

假设订单有 3 件商品(a = 3, b= 5, c = 3),现在发送了 1 批商品(a = 1, b = 2, c = 0),现在是第二个货物随物品一起发送(a = 1,b = 1,c = 1)。我想要两批货物的数量。所以我期望项目(a = 2,b = 3,c = 1),我目前得到项目(a = 1,b = 2)+ 项目(a = 1,b = 1,c = 1)。因此,我循环浏览的货件列表不止一次出现。

我认为可能是联合,但不知道如何组合:/

更新我的解决方案

我无法使用 lambda 表达式完成此操作,所以我 必须执行以下解决方案才能获得我想要的结果。我希望 这有助于其他人寻找解决方法。

//calculate quantity of total shipped items from each shipment
            List<ShipmentItem> alreadyShippedItemsList = new List<ShipmentItem>();
            Dictionary<int, int> alreadyShippedItems = new Dictionary<int, int>();

            var shippedItems = _orderService.GetOrderById(shipment.OrderId).Shipments
            .Where(x => x.ShippedDateUtc != null)
            .SelectMany(x => x.ShipmentItems)
            .ToList();

            //create a list of shipment items
            for (int i = 1; i <= shipmentsList.Count - 1; i++)
            {
                var si = shipmentsList[i];

                var sii = si.ShipmentItems.ToList();

                foreach (var item in sii)
                {
                    var itemInList = alreadyShippedItemsList.Where(x => x.OrderItemId == item.OrderItemId).FirstOrDefault();
                    int sum = 0;

                    //create a list of shipment items and check for duplicate items
                    if (itemInList == null)
                    {
                        alreadyShippedItems.Add(item.OrderItemId, item.Quantity);
                        alreadyShippedItemsList.Add(item);
                    }
                    else
                    {
                        //if duplicate item is found update the quantity in the dictionary
                        sum = itemInList.Quantity + item.Quantity;
                        alreadyShippedItems[item.OrderItemId] = sum;
                    }
                }
            }

【问题讨论】:

  • 取决于您的要求,这是“加入”还是“联合”。 Perharp,如果您能提供您的数据和所需的输出,对我们来说应该会更容易
  • @Jacky 看到我更新的问题,添加了所需的输出。
  • @Sujit.Warrier 所以 1 个订单可能有 3 批货,每批货可以包含订单中任意数量的商品。
  • 所以我希望所有货物中的所有物品都合并在一起
  • 考虑一个 Shipment 包含唯一的 ShipmentItems 但共享 OrderItems。

标签: c# asp.net lambda nopcommerce


【解决方案1】:

您需要使用SelectMany,它会将list 展平

var shippedItems = _orderService.GetOrderById(shipment.OrderId).Shipments
.Where(x => x.ShippedDateUtc != null && x.OrderId == shipment.OrderId)
.SelectMany(x => x.ShipmentItems)
.ToList();

【讨论】:

  • 这仍然没有按预期工作。查看我更新的问题,有我应该得到的输出示例。感谢您的帮助:)
  • 这似乎是我谷歌搜索的正确解决方案。但是列表并没有展平,所以同一个项目不止一次地出现在列表中。 :(
  • 也许您需要将.Where 应用到ShippingItems
【解决方案2】:

你在错误的地方使用了 Distinct

var shippedItems = _orderService.GetOrderById(shipment.OrderId).Shipments
.Where(x => x.ShippedDateUtc != null && x.OrderId == shipment.OrderId)
.Select(x => x.ShipmentItems).Distinct()
.ToList();

使用此Correct way to override Equals() and GetHashCode() 覆盖 ShipmentItems 类的 Equals 函数并直接使用 distinct 或执行两个步骤

 var distinctShippedItemIds = _orderService.GetOrderById(shipment.OrderId).Shipments
.Where(x => x.ShippedDateUtc != null && x.OrderId == shipment.OrderId)
.Select(x => x.ShipmentItems.OrderItemId).Distinct()
.ToList();

List<ShippingItems> UniqueItemList=new List<ShippingItems>();
 foreach(int OrderId in distinctShippedItemIds)
 {
     var shippedItems = _orderService.GetOrderById(shipment.OrderId).Shipments
.Where(x => x.ShippedDateUtc != null && x.OrderId == OrderId)
.Select(x => x.ShipmentItems).FirstOrDefault();
      if(shippedItems !=null)
      {
         UniqueItemList.Add(shippedItems);
      }
 }

【讨论】:

  • 该死的我以为 ShipmentItems 是一个 Int 属性
  • Distinct 不起作用,因为运行时不知道是什么使两个装运项相等。您将不得不覆盖 ShipmentItems 类的 equals() 和 gethashcodemethod() 将此信息提供给运行时。使用此链接stackoverflow.com/questions/9317582/…
  • 当我将鼠标悬停在上面时,发货项目是ICollection&lt;ShipmentItem&gt; Shipment.ShipmentItems。这让我很难过:(
  • 您是否覆盖了您的 shippingitems 类中的 equals 方法?应该能解决你的问题
  • 您的编辑部分可以在一个语句中完成。看我的回答
【解决方案3】:

我可能会误会你,但这是你想要的吗?

SELECT * FROM [ShipmentItem]
INNER JOIN [Shipment] ON [ShipmentItem].[ShipmentId] = [Shipment].[Id]
WHERE [Shipment].[ShippedDateUtc] IS NOT NULL AND [Shipment].[OrderId] = @OrderId

这样就可以了

var shippedItems = _orderService.GetOrderById(orderId)
        .Shipments
        .Where(s => s.ShippedDateUtc != null)
        .SelectMany(s => s.ShipmentItems)
        .ToList();

示例

编辑

如果你想获取订单商品,你必须这样做

var orderItems = _orderService
    .GetOrderById(orderId)
    .Shipments
    .Where(s => s.ShippedDateUtc != null)
    .SelectMany(s => s.ShipmentItems)
    .Select(si => _orderService.GetOrderItemById(si.OrderItemId))
    .Distinct()
    .ToList();

或者如果你想产生更少的数据库查询

var orderItems = _orderService
    .GetOrderById(orderId)
    .Shipments
    .Where(s => s.ShippedDateUtc != null)
    .SelectMany(s => s.ShipmentItems)
    .Select(si => si.OrderItemId)
    .Distinct()
    .Select(id => _orderService.GetOrderItemById(id))
    .ToList();

编辑 2

包含 4 个订单项目(数量为 2)和 4 个装运的订单的 nopCommerce 数据

【讨论】:

  • 第二位代码 lambda 表达式代码不起作用。假设订单有 3 件商品(a = 3, b= 5, c = 3),现在发送了 1 批商品(a = 1,b = 2,c = 0),现在发送了第二批商品与项目(a = 1,b = 1,c = 1)。我想要两批货物的数量。所以我期望项目(a = 2,b = 3,c = 1),我目前得到项目(a = 1,b = 2)+ 项目(a = 1,b = 1,c = 1)。因此,我循环浏览的货件清单不止一次出现。希望这是有道理的。感谢您的帮助
  • 为了获得两批货物的数量,您必须按 OrderItemId 对 ShipmentItems 进行分组并一起计算数量
  • 查看我更新的问题,了解对我有用的解决方案,由于某种原因,您的解决方案对我不起作用。不过感谢您的帮助:)
猜你喜欢
  • 1970-01-01
  • 2011-05-18
  • 2020-07-02
  • 1970-01-01
  • 1970-01-01
  • 2023-03-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多