【问题标题】:Entity Framework bulk insert with updating rows from another table实体框架批量插入,从另一个表更新行
【发布时间】:2017-09-28 18:32:10
【问题描述】:

我正在使用 Microsoft SQL Server 和实体框架。我有 N 个(例如 10 000 个)要插入的项目。在插入每个项目之前,我需要插入或更新现有组。由于性能低下,它不能很好地工作。这是因为我生成了太多查询。每次在循环中,我都通过三个(已编入索引的)参数查询Groups 表来查找组。

我正在考虑首先使用 WHERE IN 查询 (Groups.Where(g => owners.Contains(g.OwnerId) && .. ) 查询所有组,但我记得此类查询受参数数量的限制。

也许我应该写一个存储过程?

这是我的示例代码。我正在使用 IUnitOfWork 模式来包装 EF DbContext:

public async Task InsertAsync(IItem item)
{
    var existingGroup = await this.unitOfWork.Groups.GetByAsync(item.OwnerId, item.Type, item.TypeId);

    if (existingGroup == null)
    {
        existingGroup = this.unitOfWork.Groups.CreateNew();
        existingGroup.State = GroupState.New;
        existingGroup.Type = item.Code;
        existingGroup.TypeId = item.TypeId;
        existingGroup.OwnerId = item.OwnerId;
        existingGroup.UpdatedAt = item.CreatedAt;

        this.unitOfWork.Groups.Insert(existingGroup);
    }
    else
    {
        existingGroup.UpdatedAt = item.CreatedAt;
        existingGroup.State = GroupState.New;

        this.unitOfWork.Groups.Update(existingGroup);
    }

    this.unitOfWork.Items.Insert(item);
}

foreach(var item in items)
{
    InsertAsync(item);
}

await this.unitOfWork.SaveChangesAsync();

【问题讨论】:

    标签: c# sql-server entity-framework insert bulkinsert


    【解决方案1】:

    批量插入时提高性能的三个关键要素:

    • AutoDetectChangesEnabledValidateOnSaveEnabled 设置为false:

    _db.Configuration.AutoDetectChangesEnabled = false; _db.Configuration.ValidateOnSaveEnabled = false;

    • 将您的插入分解成段,使用相同的DbContext,然后重新创建它。段的大小因用例而异,在重新创建上下文之前,我在大约 100 个元素时取得了最佳性能。这是由于观察了 DbContext 中的元素。 还要确保不要为每个插入重新创建上下文。 (参见Slauma的答案Fastest Way of Inserting in Entity Framework

    • 检查其他表时,请确保尽可能使用IQueryable,并且仅在必要时使用ToList()FirstOrDefault()。由于ToList()FirstOrDefault() 加载对象。 (见Richard Szalay的答案What's the difference between IQueryable and IEnumerable

    在您描述的场景中批量插入时,这些技巧对我的帮助最大。还有其他的可能性。例如 SP 和 BulkInsert 函数。

    【讨论】:

    • 我已使用您的建议禁用 AutoDetectChanges 以进行少数查询。不幸的是,EF 生成了太多繁重的查询,而且我还将少数 EF 查询重写为原始 SQL 查询和存储过程。现在工作正常。
    • 很高兴听到这个消息。好吧,在某些情况下,这样做可能是最好的。有时 EF 只是让事情变得过于复杂,但我们必须注意我们自己不要这样做。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-03
    • 2017-02-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多