C#实体框架批量更新

时间:2018-06-24 10:11:59

标签: c# entity-framework-6

更新列表中的多个记录以加快处理速度的最佳方法是什么?

目前,我正在更新大约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.

2 个答案:

答案 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();
}
相关问题