以最佳存储方式和工作单元批量插入数据库

时间:2019-05-04 05:54:49

标签: c# performance entity-framework repository-pattern unit-of-work

我想在我的存储库中插入800k行,然后提交。我将每15k记录发送到存储库并提交,但速度太慢。

        foreach (var imei in command.IMEIItems) {

            var newIMEI = new IMEI(imei.IMEINumber, command.PromotionId);
            _imeiRepository.Add(newIMEI);
        }

        _unitOfWork.Commit();

我的问题是关于foreach循环的。它太慢而无法添加到存储库中。 提交很快。

我的资料库:

         public virtual TEntity Add(TEntity entity)
    {
        if (entity != null)
        {
            TEntity addedTEntity = ObjectSet.Add(entity); // add new item in this set
            return addedTEntity;
        }
        else
        {
            throw new ArgumentNullException();
        }

    }

     protected virtual IDbSet<TEntity> ObjectSet
    {
        get
        {
            return _unitOfWork.CreateSet<TEntity>();
        }
    }

     public virtual IDbSet<TEntity> CreateSet<TEntity>() where TEntity : 
      class
    {
        return base.Set<TEntity>();
    }

2 个答案:

答案 0 :(得分:0)

一个建议,假设您的Repo方法是线程安全的-

考虑到大数据量,您可以尝试使用Parallel.for吗?像this

但是,如果您的数据量较小,则考虑到CPU上下文切换开销,Parallel.For的效率可能会降低。

因此,可能值得检查输入集合的大小,然后在正常与并行之间进行决定,

答案 1 :(得分:0)

添加vs添加范围

使用Add方法添加多个实体是一个非常常见的错误。实际上,是 INSANELY 缓慢的DetectChanges方法。

  • 添加每条记录后,添加方法DetectChanges。
  • 添加所有记录后,AddRange方法DetectChanges。

请参阅:Entity Framework - Performance Add


要解决您的问题,

这个想法可能是在您的存储库中添加一个新方法AddRange。但是,您将面临另一个问题,因为IDbSet没有AddRange方法,但是DbSet有。因此,也许您需要进行投射。


编辑:回答评论

  

我需要如何铸造?

这实际上取决于您的IDbSet<TEntity>。我的意思是,这不是接口的实例,它必须从类继承。

它可能是DbSet<TEntity>的一个实例,因此,只有这种情况,您才需要强制转换

((DbSet<TEntity>)ObjectSet).AddRange(items);