更新列表中的多个记录以加快处理速度的最佳方法是什么?
目前,我正在更新大约15000种产品,每种产品具有3种不同的价格,并且需要一整天才能完成。
我需要立即在代码端更新所有价格,然后一次性将这些更改提交到数据库中,而不是获取每个库存项目,更新其值,然后将其附加到上下文中。每次抓取都会导致延迟。
代码
public void UpdatePricesFromInventoryList(IList<Domain.Tables.Inventory> invList)
{
var db = new UniStockContext();
foreach (var inventory in invList)
{
Domain.Tables.Inventory _inventory = db.Inventories
.Where(x => x.InventoryID == inventory.InventoryID)
.FirstOrDefault();
if (inventory.Cost.HasValue)
_inventory.Cost = inventory.Cost.Value;
else
_inventory.Cost = 0;
foreach (var inventoryPrices in inventory.AccInventoryPrices)
{
foreach (var _inventoryPrices in _inventory.AccInventoryPrices)
{
if (_inventoryPrices.AccInventoryPriceID == inventoryPrices.AccInventoryPriceID)
{
_inventoryPrices.ApplyDiscount = inventoryPrices.ApplyDiscount;
_inventoryPrices.ApplyMarkup = inventoryPrices.ApplyMarkup;
if (inventoryPrices.Price.HasValue)
_inventoryPrices.Price = inventoryPrices.Price.Value;
else
_inventoryPrices.Price = _inventory.Cost;
if (inventoryPrices.OldPrice.HasValue)
{
_inventoryPrices.OldPrice = inventoryPrices.OldPrice;
}
}
}
}
db.Inventories.Attach(_inventory);
db.Entry(_inventory).State = System.Data.Entity.EntityState.Modified;
}
db.SaveChanges();
db.Dispose();
}
我还尝试根据此SOQ Entity Framework update/insert multiple entities处理我的代码 这给了我错误。详细信息如下:
代码:
public void UpdatePricesFromInventoryListBulk(IList<Domain.Tables.Inventory> invList)
{
var accounts = new List<Domain.Tables.Inventory>();
var db = new UniStockContext();
db.Configuration.AutoDetectChangesEnabled = false;
foreach (var inventory in invList)
{
accounts.Add(inventory);
if (accounts.Count % 1000 == 0)
{
db.Set<Domain.Tables.Inventory>().AddRange(accounts);
accounts = new List<Domain.Tables.Inventory>();
db.ChangeTracker.DetectChanges();
db.SaveChanges();
db.Dispose();
db = new UniStockContext();
}
}
db.Set<Domain.Tables.Inventory>().AddRange(accounts);
db.ChangeTracker.DetectChanges();
db.SaveChanges();
db.Dispose();
}
错误:
An entity object cannot be referenced by multiple instances of IEntityChangeTracker.
答案 0 :(得分:1)
我建议更改以下内容:
Domain.Tables.Inventory _inventory = db.Inventories
.Where(x => x.InventoryID == inventory.InventoryID)
.FirstOrDefault();
收件人
Domain.Tables.Inventory _inventory = db.Inventories
.Single(x => x.InventoryID == inventory.InventoryID);
我仍将添加db.Configuration.AutoDetectChangesEnabled = false;获取上下文后,还可以使用AsNoTracking: Turn off EF change tracking for any instance of the context
答案 1 :(得分:-1)
那是因为您在每个循环中都被命中数据库上下文以提高性能,因此您应该一击获得所有清单,这是您的问题,请尝试以下代码,您将注意到性能:
public void UpdatePricesFromInventoryList(IList<Domain.Tables.Inventory> invList)
{
var db = new UniStockContext();
invIdsArray = invList.select(x => x.InventoryID).ToArray();
IList<Domain.Tables.Inventory> invListFromDbByOneHit = db.Inventories.Where(x => invIdsArray.Contains(x.InventoryID)).Tolist();
foreach (var inventory in invListFromDbByOneHit)
{
//Domain.Tables.Inventory _inventory = db.Inventories
//.Where(x => x.InventoryID == inventory.InventoryID)
//.FirstOrDefault();
if (inventory.Cost.HasValue)
_inventory.Cost = inventory.Cost.Value;
else
_inventory.Cost = 0;
foreach (var inventoryPrices in inventory.AccInventoryPrices)
{
foreach (var _inventoryPrices in _inventory.AccInventoryPrices)
{
if (_inventoryPrices.AccInventoryPriceID == inventoryPrices.AccInventoryPriceID)
{
_inventoryPrices.ApplyDiscount = inventoryPrices.ApplyDiscount;
_inventoryPrices.ApplyMarkup = inventoryPrices.ApplyMarkup;
if (inventoryPrices.Price.HasValue)
_inventoryPrices.Price = inventoryPrices.Price.Value;
else
_inventoryPrices.Price = _inventory.Cost;
if (inventoryPrices.OldPrice.HasValue)
{
_inventoryPrices.OldPrice = inventoryPrices.OldPrice;
}
}
}
}
db.Inventories.Attach(_inventory);
db.Entry(_inventory).State = System.Data.Entity.EntityState.Modified;
}
db.SaveChanges();
db.Dispose();
}