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

SqlBulkCopy и Entity Framework

Мой текущий проект состоит из 3 стандартных слоев: данных, бизнеса и презентации. Я хотел бы использовать объекты данных для всех моих потребностей в доступе к данным. Часть функциональности приложения будет заключаться в том, что ему нужно будет скопировать все данные в плоском файле в базу данных. Файл не такой большой, поэтому я могу использовать SqlBulkCopy. Я нашел несколько статей, посвященных использованию класса SqlBulkCopy в .NET. Тем не менее, все статьи используют DataTables для перемещения данных вперед и назад.

Есть ли способ использовать объекты данных вместе с SqlBulkCopy или мне придется использовать DataTables?

4b9b3361

Ответ 1

Вам нужно будет преобразовать объекты в IDataReader или DataTable.

Существует небольшой вспомогательный класс, предназначенный для: http://archive.msdn.microsoft.com/LinqEntityDataReader/Release/ProjectReleases.aspx?ReleaseId=389

ИЗМЕНИТЬ: msdn ссылка сломана, alt copy можно найти здесь: https://github.com/matthewschrager/Repository/blob/master/Repository.EntityFramework/EntityDataReader.cs

Затем вы можете использовать SqlBulkCopy следующим образом:

var sbCopy= new SqlBulkCopy(connectionString);
sbCopy.DestinationTableName = "TableName";
sbCopy.WriteToServer(entitiesList.AsDataReader()); 

Ответ 2

Мы попытались и протестировали несколько подходов при массовой загрузке с использованием EF и, в конечном итоге, пошли с табличными параметрами для получения максимальной производительности в диапазоне размеров строк. У меня нет цифр, но я знаю, что это Эффективность bcp/BULK INSERT и Table-Valued Parameters является определяющим фактором.

Первоначально мы использовали SqlBulkCopy в сочетании с адаптером, который взял IEnumerable<T> и создал IDataReader. Он также создал соответствующие метаданные для SqlBulkCopy. Преимущество заключалось в том, что импорт - это только код. В качестве основы для этого был использован код, который был опубликован @davehogan.

Таблично-значные параметры требуют хранимой процедуры и табличного типа, определенных в базе данных. Если вы используете код сначала, вы можете выполнить SQL, чтобы создать их как часть своего создания script. Хотя это большая работа, мы обнаружили, что мы получили значительно более последовательную и более быструю пропускную способность строк в базе данных.

Кроме того, стоит рассмотреть не объемную вставку в вашу основную таблицу. Мы используем таблицу кучи temp и добавляем к ней кластерный индекс после импорта данных. Затем мы выполняем a MERGE между таблицей temp и основной таблицей. Это позволяет не блокировать индекс основной таблицы при вставке и улучшает concurrency. Мы используем этот метод с частотой выше 2500 строк на секунду.

Сообщите мне, если вы хотите получить дополнительную информацию.

Ответ 3

Вы можете рассматривать набор данных как сериализацию объекта данных. Однако, вообще говоря, я думаю, что SqlBulkCopy - это таблица для таблицы вещей, поэтому причина для данных datatables.

Ответ 4

SqlBulkCopy использует IDataReader при вызове метода WriteToServer, поэтому вы должны иметь возможность реализовать IDataReader на основе коллекции, которая является IEnumerable. Это позволит вам взять набор объектов и вызвать SqlBulkCopy, используя вашу реализацию IDataReader.

Ответ 5

Вы можете использовать Bulk package. Версия Bulk Insert 1.0.0 используется в проектах с инфраструктурой Entity >= 6.0.0. Более подробное описание можно найти в следующей ссылке: Исходный код Bulkoperation

Ответ 7

SqlBulkCopy - это прямая, почти байт-подобная передача данных строк от клиента к SQL Server. Это простой способ получить данные в SQL Server.

Однако его производительность заключается в действительно "объемных" операциях. Сотни или тысячи строк не обязательно достаточно высоки, чтобы оправдать использование. Десятки от тысячи до миллионов строк - это производительность SqlBulkCopy будет действительно сиять. И, в конце концов, все, о чем мы действительно говорим, это получение данных на сервер.

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

Кроме того, данные TVP записываются на диск (в виде данных таблицы temp), а затем доступны для размещения в ваших таблицах. SqlBulkCopy способен идти прямо на ваш стол... производительность в этом случае значительно быстрее, однако нужно балансировать скорость для concurrency.

Я думаю, что общее правило состоит в том, что если у вас есть несколько строк для рассмотрения, подумайте TVP, и если у вас много тысяч строк, подумайте о том, чтобы получить его на SQL Server так быстро, как возможно, через SqlBulkCopy.

Ответ 8

Как дополнение к ответу @DaveHogan,

Теперь есть новые библиотеки, которые позволяют выполнять Bulk Insert (используя SqlBulkCopy под капотом) для Entity Framework с использованием сущностей данных вместо DataTable.

Отказ от ответственности: Я являюсь владельцем проекта Расширения платформы Entity

Эта библиотека не является бесплатной, но позволяет легко выполнять:

  • BulkSaveChanges
  • BulkInsert
  • BulkUpdate
  • BulkDelete
  • BulkMerge

Под капотом используется SqlBulkCopy. Использование метода расширения упрощает/ускоряет процесс кодирования настраиваемого решения для каждой используемой массовой вставки.

Пример

// Easy to use
context.BulkSaveChanges();

// Easy to customize
context.BulkSaveChanges(bulk => bulk.BatchSize = 100);

низкая производительность

Мне жаль, что вы плохо себя чувствуете,

Убедитесь, что вы не включаете время от какой-либо распространенной ошибки, например, забываете JIT Compile, используя Add вместо AddRange, которые влияют на производительность теста, но не связаны с нашей библиотекой.

Большинство людей сообщают о повышении производительности в 25-50 раз, исключая все распространенные ошибки производительности.

Смотрите: Расширения Entity Framework - контрольная таблица