如何将库存更新的嵌套foreach简化为单个循环(LINQ实现)
优化仓库库存与预留项更新代码:嵌套循环转单循环+LINQ优化
需求说明
现有warehouseReservationItems(仓库预留项列表)和ExistingInventories(现有库存列表)两个集合,需根据输入的processedItems列表完成数据更新。当前实现采用嵌套foreach循环:外层遍历processedItems条目匹配对应仓库预留项,内层遍历BinInventoryList匹配库存,执行预留量、在手量更新及错误校验。需要将嵌套循环简化为单个foreach循环,结合LINQ优化查询逻辑。
输入结构示例
// processedItems输入列表结构示例 { "reservationId": 0, "warehouseId": 0, "itemList": [ { "itemId": "string", "rejected": true, "binInventoryList": [ { "binId": 0, "qtyFilled": 0 } ] } ] }
当前实现代码(嵌套循环版)
foreach (var item in processedItems) // 遍历输入的每个条目 { // 匹配对应的仓库预留项 var modifiedItem = warehouseReservationItems?.FirstOrDefault(wri => wri.ItemId == item.ItemId); // 筛选需要更新的库存项 var inventoriesToUpdate = item.BinInventoryList .SelectMany(rib => existingInventories.Where(winv => winv.ItemId == modifiedItem.ItemId && rib.BinId == winv.BinId)) .ToList(); foreach (var modifiedInventory in inventoriesToUpdate) { // 匹配当前库存对应的Bin信息 var bin = item.BinInventoryList.FirstOrDefault(bin => bin.BinId == modifiedInventory.BinId); // 更新预留量 if (modifiedItem.QtyFilled <= modifiedItem.QtyOrdered) { if (modifiedItem.QtyFilled + bin.QtyFilled > modifiedItem.QtyOrdered) { modifiedInventory.QtyReserved = (modifiedInventory.QtyReserved - modifiedItem.QtyOrdered) + modifiedItem.QtyFilled; } else { modifiedInventory.QtyReserved -= bin.QtyFilled; // 扣除已填充的预留量 } } // 更新在手库存量 if (bin.QtyFilled <= modifiedInventory.QtyOnHand) { modifiedItem.QtyFilled += bin.QtyFilled; // 累计已填充数量 modifiedInventory.QtyOnHand -= bin.QtyFilled; // 从在手库存中扣除已填充量 } else { // 记录错误:填充量超过在手库存 _errorDictionary.Add($"{modifiedInventory.ItemId}({modifiedInventory.BinId})", new[] { $"填充数量({bin.QtyFilled})超过在手库存数量({modifiedInventory.QtyOnHand})" }); } updatedInventory.Add(modifiedInventory); } // 更新预留项状态 modifiedItem.SetReservationItemStatus(modifiedItem.QtyFilled, modifiedItem.QtyOrdered); }
优化后的单循环+LINQ实现
核心思路是用LINQ的Join操作提前关联processedItems、仓库预留项、Bin信息、现有库存,生成包含所有必要数据的扁平集合,再通过一次foreach遍历完成所有更新,避免嵌套循环和重复查询。
// 提前关联所有需要的数据,生成扁平集合 var updateData = processedItems // 关联仓库预留项 .Join(warehouseReservationItems, item => item.ItemId, resItem => resItem.ItemId, (item, resItem) => new { item, resItem }) // 展开每个条目下的BinInventoryList .SelectMany(j => j.item.BinInventoryList.Select(bin => new { j.item, j.resItem, bin })) // 关联对应的现有库存 .Join(existingInventories, j => new { j.resItem.ItemId, j.bin.BinId }, inv => new { inv.ItemId, inv.BinId }, (j, inv) => new { j.resItem, j.bin, inv }) .ToList(); // 单循环完成所有更新操作 foreach (var data in updateData) { var modifiedItem = data.resItem; var bin = data.bin; var modifiedInventory = data.inv; // 更新预留量逻辑 if (modifiedItem.QtyFilled <= modifiedItem.QtyOrdered) { if (modifiedItem.QtyFilled + bin.QtyFilled > modifiedItem.QtyOrdered) { modifiedInventory.QtyReserved = (modifiedInventory.QtyReserved - modifiedItem.QtyOrdered) + modifiedItem.QtyFilled; } else { modifiedInventory.QtyReserved -= bin.QtyFilled; } } // 更新在手库存逻辑 if (bin.QtyFilled <= modifiedInventory.QtyOnHand) { modifiedItem.QtyFilled += bin.QtyFilled; modifiedInventory.QtyOnHand -= bin.QtyFilled; updatedInventory.Add(modifiedInventory); } else { _errorDictionary.Add($"{modifiedInventory.ItemId}({modifiedInventory.BinId})", new[] { $"填充数量({bin.QtyFilled})超过在手库存数量({modifiedInventory.QtyOnHand})" }); } } // 统一更新所有预留项的状态(去重避免重复调用) foreach (var resItem in updateData.Select(d => d.resItem).Distinct()) { resItem.SetReservationItemStatus(resItem.QtyFilled, resItem.QtyOrdered); }
优化点说明
- 用LINQ多表关联替代嵌套循环和重复的
FirstOrDefault查询,减少冗余操作,提升代码可读性 - 提前整合所有数据为扁平集合,避免内层循环中重复查找Bin信息
- 预留项状态更新统一放到循环外(去重处理),减少重复调用次数
内容的提问来源于stack exchange,提问作者Andi
相关产品推荐
相关产品推荐

