SqlBulkCopy и Entity Framework - PullRequest
       12

SqlBulkCopy и Entity Framework

16 голосов
/ 31 марта 2010

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

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

Ответы [ 7 ]

21 голосов
/ 06 февраля 2012

Вам необходимо преобразовать сущности в IDataReader или DataTable.

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

РЕДАКТИРОВАТЬ: ссылка MSDN не работает, альтернативная копия может быть найдена здесь: https://github.com/matthewschrager/Repository/blob/master/Repository.EntityFramework/EntityDataReader.cs

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

var sbCopy= new SqlBulkCopy(connectionString);
sbCopy.DestinationTableName = "TableName";
sbCopy.WriteToServer(entitiesList.AsDataReader()); 
6 голосов
/ 14 октября 2013

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

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

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

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

Дайте мне знать, если вам нужна дополнительная информация.

2 голосов
/ 27 апреля 2017

Для EFCore есть BulkExtensions (Вставка, Обновление InsertOrUpdate, Удалить):
Ссылка: https://github.com/borisdj/EFCore.BulkExtensions
Может также быть установлена ​​через Nuget

2 голосов
/ 17 апреля 2017

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

1 голос
/ 26 сентября 2016

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

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

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

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

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

1 голос
/ 13 апреля 2010

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

1 голос
/ 31 марта 2010

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

...