Подтвердить что ты не робот

Эффективный способ делать массовую вставку/обновление с помощью Entity Framework

У меня есть список объектов, и я хочу вставить их в базу данных. Если объект уже существует в базе данных, тогда он должен быть пропущен. Если его в базе данных, но с разными значениями, то его необходимо обновить.

Есть ли способ сделать это иначе, чем вызов db для каждого элемента?

Мой план состоит в том, чтобы попробовать вставить, если выбрано исключение исключительного ограничения на ключ, затем выполните обновление.

4b9b3361

Ответ 1

Просто не используйте Entity Framework в этом случае. Просто используйте хранимую процедуру (как зависит от версии/подхода, который вы используете с EF, вам может потребоваться расширить ваш DbContext или добавить сопоставление из модели сущности).

Если вы используете SQL Server, то в своей процедуре хранилища используйте команду MERGE, которая эффективно выполняет точно, что вам нужно: вставить, если оно не существует, или обновить, если это произойдет. Все в одном эффективном SQL-запросе.

Ответ 2

EF не подходит для вставок BULK. Для 1000s записей это нормально, но большие числа (100k plus) медленны.

Если вы планируете использовать EF.

  • попробуйте метод AddOrUpdate (вместо вставки/обновления)
  • Отключить отслеживание,
  • фиксировать каждые 1000 записей или меньше.

например,

Context.Set<TPoco>().AddOrUpdate(poco);
//...
Context.Configuration.AutoDetectChangesEnabled =
//..
Context.SaveChanges();

Если вы копируете несвязанные данные, вы можете попробовать эти таблицы параллельно (doh)

Ответ 3

Я сделал расширение для этого https://efbulkinsert.codeplex.com/

и очень просто использовать

using(var context = new MyDbContext())
{
    context.BulkInsert(hugeCollectionOfEntities);
}

Ответ 4

  • Создайте временную таблицу: SqlCommand (string.Format("SELECT TOP 0 * INTO {0} FROM {1}...

  • Массовая вставка данных в него - Entity Framework Extended, упомянутый выше, должен быть изменен для поддержки имени таблицы temp, но в противном случае находится на правильном пути - или сверните немного кода и используйте SqlBulkCopy.

  • Создайте оператор MERGE.

Если вы сокрываете список свойств, вы можете сделать (2) и (3) общий. Я могу читать и объединять 150 000 строк за 20 секунд.

Ответ 5

Есть репозиторий github, который содержит оба полезных метода: BulkInsert и BulkUpdate с использованием MySql и EF6+.

BulkUpdate/BulkInsert в основном считывает все свойства из вашей общей сущности, а затем создает массовый запрос для вас.

Ps: Это было разработано для моих нужд, и проект открыт для тех, кто хочет улучшить его или изменить его на лучшее решение, которое будет полезно сообществу.

PS2: Если это не решает проблему, попробуйте внести изменения в проект, чтобы улучшить и достичь того, чего вы хотите, по крайней мере, это хорошее начало.

Пожалуйста, посмотрите на main.cs