массовая вставка в базу данных в шаблоне хранилища и единицах работы с наилучшей производительностью - PullRequest
0 голосов
/ 04 мая 2019

Я хочу вставить строку 800 КБ в мой репозиторий, а затем зафиксировать.Я отправляю каждые 15 тыс. записей в хранилище и фиксирую их, но это слишком медленно.

        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 голосов
/ 05 мая 2019

Добавить против AddRange

Это очень распространенная ошибка при использовании метода Add для добавления нескольких объектов. Фактически, это метод DetectChanges, который INSANELY slow.

  • Метод Add DetectChanges после каждой добавленной записи.
  • Метод AddRange DetectChanges после добавления всех записей.

См .: Entity Framework - Performance Add


Чтобы решить вашу проблему,

Идея, вероятно, заключается в добавлении нового метода AddRange в ваш репозиторий. Однако вы столкнетесь с другой проблемой, поскольку IDbSet не имеет метода AddRange, а DbSet. Так что, возможно, вам нужно будет сделать бросок.


РЕДАКТИРОВАТЬ: ответить на комментарий

как разыграть мне нужно будет сделать?

Это зависит от того, что в действительности является вашим IDbSet<TEntity>. Я имею в виду, что это не экземпляр интерфейса, он должен наследоваться от класса.

Это, вероятно, экземпляр DbSet<TEntity>, так что если это так, вам нужно только разыграть его

((DbSet<TEntity>)ObjectSet).AddRange(items);
0 голосов
/ 04 мая 2019

Одно предложение, предполагая, что ваш метод Repo является поточно-ориентированным -

Можете ли вы попробовать Parallel.for, учитывая большой размер данных. Что-то вроде это

Однако, если ваш размер данных относительно мал, тогда Parallel.For может быть менее эффективным, учитывая издержки переключения контекста ЦП.

Так что, возможно, стоит проверить размер входной коллекции и затем выбрать между нормалью для и параллелью для,

...