有什么方法可以将多个嵌套的 create foreach 循环展平为一个批量 create/insert?
Any way to flatten multiple nested create foreach loops to a bulk create/insert?
我有这样一种情况,我试图提高嵌套 foreach 循环内的一堆创建的性能。它用于创建工单。在生成工作订单之前,可以添加任意数量的属性、供应商和工作订单 items/costs。每添加一个 property/vendor 都会生成一个工作订单,因此所有选定的供应商都会为每个 属性 创建一个工作订单。如果添加太多,那会变得一团糟。不幸的是,这些是客户希望系统运行的方式,所以我不能重新设计它(或者它已经是)。
代码经过简化,只包含相关部分 -
DbContext dbContext = new DbContext();
foreach (Property property in properties)
{
foreach (Vendor vendor in vendors)
{
WorkOrder wo = new WorkOrder();
WorkOrder.PropertyID = property.PropertyID;
WorkOrder.VendorID = vendor.VendorID;
dbContext.AddObject(wo);
dbContext.SaveChanges();
foreach (WorkOrderItemViewModel itemView in workOrderItemViewModels)
{
WorkOrderItem item = new WorkOrderItem();
item.WorkOrderID = wo.WorkOrderID;
dbContext.AddObject(item);
dbContext.SaveChanges();
foreach (WorkOrderItemCostViewModel costView in workOrderItemCostViewModels)
{
WorkOrderItemCost cost = new WorkOrderItemCost();
cost.WorkOrderItemID = item.WorkOrderItemID;
dbContext.AddObject(cost);
dbContext.SaveChanges();
}
}
}
}
这是很多嵌套的创建。如果他们在工单中添加太多东西,可能会花费很长时间。每件只有 2 个对象,它转换为:
2 个属性 x 2 个供应商 = 4 个工单
2 个工作订单项目 x 4 个工作订单 = 8 个工作订单项目
2 项成本 x 8 项工作订单项 = 16 项成本
总计 = 28 个创建
问题是我需要当前对象的先前对象的 ID。所以在我创建下一个对象之前需要创建它们。我看过一些解决方案 - 例如 SQLite 或批量插入....但看起来它们都需要采用标准 sql 字符串格式。我已经尝试研究是否可以将 linq 输出到实体生成的 sql 查询到字符串,但我没有发现任何有用的东西。
有什么好的方法可以在客户的规范中重写它以获得急需的性能提升吗?
我想通了。我认为这行不通,因为我认为主键不会在 creation/saving 更改后填充到模型中(但它们确实如此)- 在这里(非常简单):
DbContext dbContext = new DbContext();
List<WorkOrder> workOrders = new List<WorkOrder>();
List<WorkOrderItem> workOrderItems = new List<WorkOrderItem>();
foreach (Property property in properties)
{
foreach (Vendor vendor in vendors)
{
WorkOrder wo = new WorkOrder();
WorkOrder.PropertyID = property.PropertyID;
WorkOrder.VendorID = vendor.VendorID;
dbContext.AddObject(wo);
workOrders.Add(wo);
}
}
dbContext.SaveChanges();
foreach (WorkOrder wo in workOrders)
{
foreach (WorkOrderItemViewModel itemView in workOrderItemViewModels)
{
WorkOrderItem item = new WorkOrderItem();
item.WorkOrderID = wo.WorkOrderID;
dbContext.AddObject(item);
workOrderItems.Add(item);
}
}
dbContext.SaveChanges();
foreach (WorkOrderItem item in workOrderItems)
{
foreach (WorkOrderItemCostViewModel costView in workOrderItemCostViewModels)
{
WorkOrderItemCost cost = new WorkOrderItemCost();
cost.WorkOrderItemID = item.WorkOrderItemID;
dbContext.AddObject(cost);
}
}
dbContext.SaveChanges();
只使用dbContext.SaveChanges();
一次将优化性能。
改用这个:
DbContext dbContext = new DbContext();
foreach (Property property in properties)
{
foreach (Vendor vendor in vendors)
{
WorkOrder wo = new WorkOrder();
WorkOrder.PropertyID = property.PropertyID;
WorkOrder.VendorID = vendor.VendorID;
dbContext.AddObject(wo);
foreach (WorkOrderItemViewModel itemView in workOrderItemViewModels)
{
WorkOrderItem item = new WorkOrderItem();
item.WorkOrderID = wo.WorkOrderID;
dbContext.AddObject(item);
foreach (WorkOrderItemCostViewModel costView in workOrderItemCostViewModels)
{
WorkOrderItemCost cost = new WorkOrderItemCost();
cost.WorkOrderItemID = item.WorkOrderItemID;
dbContext.AddObject(cost);
}
}
}
}
dbContext.SaveChanges();
我有这样一种情况,我试图提高嵌套 foreach 循环内的一堆创建的性能。它用于创建工单。在生成工作订单之前,可以添加任意数量的属性、供应商和工作订单 items/costs。每添加一个 property/vendor 都会生成一个工作订单,因此所有选定的供应商都会为每个 属性 创建一个工作订单。如果添加太多,那会变得一团糟。不幸的是,这些是客户希望系统运行的方式,所以我不能重新设计它(或者它已经是)。
代码经过简化,只包含相关部分 -
DbContext dbContext = new DbContext();
foreach (Property property in properties)
{
foreach (Vendor vendor in vendors)
{
WorkOrder wo = new WorkOrder();
WorkOrder.PropertyID = property.PropertyID;
WorkOrder.VendorID = vendor.VendorID;
dbContext.AddObject(wo);
dbContext.SaveChanges();
foreach (WorkOrderItemViewModel itemView in workOrderItemViewModels)
{
WorkOrderItem item = new WorkOrderItem();
item.WorkOrderID = wo.WorkOrderID;
dbContext.AddObject(item);
dbContext.SaveChanges();
foreach (WorkOrderItemCostViewModel costView in workOrderItemCostViewModels)
{
WorkOrderItemCost cost = new WorkOrderItemCost();
cost.WorkOrderItemID = item.WorkOrderItemID;
dbContext.AddObject(cost);
dbContext.SaveChanges();
}
}
}
}
这是很多嵌套的创建。如果他们在工单中添加太多东西,可能会花费很长时间。每件只有 2 个对象,它转换为:
2 个属性 x 2 个供应商 = 4 个工单
2 个工作订单项目 x 4 个工作订单 = 8 个工作订单项目
2 项成本 x 8 项工作订单项 = 16 项成本
总计 = 28 个创建
问题是我需要当前对象的先前对象的 ID。所以在我创建下一个对象之前需要创建它们。我看过一些解决方案 - 例如 SQLite 或批量插入....但看起来它们都需要采用标准 sql 字符串格式。我已经尝试研究是否可以将 linq 输出到实体生成的 sql 查询到字符串,但我没有发现任何有用的东西。
有什么好的方法可以在客户的规范中重写它以获得急需的性能提升吗?
我想通了。我认为这行不通,因为我认为主键不会在 creation/saving 更改后填充到模型中(但它们确实如此)- 在这里(非常简单):
DbContext dbContext = new DbContext();
List<WorkOrder> workOrders = new List<WorkOrder>();
List<WorkOrderItem> workOrderItems = new List<WorkOrderItem>();
foreach (Property property in properties)
{
foreach (Vendor vendor in vendors)
{
WorkOrder wo = new WorkOrder();
WorkOrder.PropertyID = property.PropertyID;
WorkOrder.VendorID = vendor.VendorID;
dbContext.AddObject(wo);
workOrders.Add(wo);
}
}
dbContext.SaveChanges();
foreach (WorkOrder wo in workOrders)
{
foreach (WorkOrderItemViewModel itemView in workOrderItemViewModels)
{
WorkOrderItem item = new WorkOrderItem();
item.WorkOrderID = wo.WorkOrderID;
dbContext.AddObject(item);
workOrderItems.Add(item);
}
}
dbContext.SaveChanges();
foreach (WorkOrderItem item in workOrderItems)
{
foreach (WorkOrderItemCostViewModel costView in workOrderItemCostViewModels)
{
WorkOrderItemCost cost = new WorkOrderItemCost();
cost.WorkOrderItemID = item.WorkOrderItemID;
dbContext.AddObject(cost);
}
}
dbContext.SaveChanges();
只使用dbContext.SaveChanges();
一次将优化性能。
改用这个:
DbContext dbContext = new DbContext();
foreach (Property property in properties)
{
foreach (Vendor vendor in vendors)
{
WorkOrder wo = new WorkOrder();
WorkOrder.PropertyID = property.PropertyID;
WorkOrder.VendorID = vendor.VendorID;
dbContext.AddObject(wo);
foreach (WorkOrderItemViewModel itemView in workOrderItemViewModels)
{
WorkOrderItem item = new WorkOrderItem();
item.WorkOrderID = wo.WorkOrderID;
dbContext.AddObject(item);
foreach (WorkOrderItemCostViewModel costView in workOrderItemCostViewModels)
{
WorkOrderItemCost cost = new WorkOrderItemCost();
cost.WorkOrderItemID = item.WorkOrderItemID;
dbContext.AddObject(cost);
}
}
}
}
dbContext.SaveChanges();