Есть ли более быстрый способ использования SqlBulkCopy, чем использование DataTable?

c# sqlbulkcopy sql-server

Вопрос

Я загружаю большое количество записей в мое приложение (1 млн. +) И выполняю тонну обработки на них. Для обработки требуется, чтобы все они находились в памяти.

Впоследствии я хочу сбросить все (теперь измененные) записи в пустую таблицу.

Загрузка записей занимает всего несколько секунд, и я получаю большой массив элементов MyRecord .

Сохранение с использованием SqlBulkCopy занимает всего несколько секунд.

Однако SqlBulkCopy требует (я считаю) DataTable - и загрузка моих записей в DataTable происходит медленно - приблизительно 7500 записей в минуту, используя

dataTable.Rows.Add(myRecord.Name, myRecord.Age, ....)

Есть ли более быстрый способ выполнить этот средний шаг?

Принятый ответ

Задержка вызвана тем, что перед отправкой на сервер вам нужно все буферизовать в DataTable. Чтобы получить лучшую производительность, вы должны немедленно отправить записи в SqlBulkCopy и позволить классу использовать собственную буферизацию и пакетную обработку.

SqlBulkCopy может работать с IDataReader. Все считыватели данных ADO.NET реализуют этот интерфейс, поэтому вы можете передавать данные, которые вы читаете из любого устройства чтения данных, в SqlBulkCopy.

В других случаях, если у вас есть IEnumerable ваших объектов, вы можете использовать ObjectReader от Marc Gravel из пакета FastMember для создания IDataReader поверх IEnumerable. Этот считыватель данных не загружает все сразу, поэтому данные не кэшируются до тех пор, пока SqlBulkCopy не попросит об этом:

Копирование примера Марка Гравеля:

IEnumerable<SomeType> data = ... 

using(var bcp = new SqlBulkCopy(connection)) 
using(var reader = ObjectReader.Create(data, "Id", "Name", "Description")) 
{ 
  bcp.DestinationTableName = "SomeTable"; 
  bcp.WriteToServer(reader); 
}

Популярные ответы

Я не знаю, в чем проблема. Программа ниже работает под вторым. Я подозреваю, что медленная скорость связана с чтением данных и не записью в DataTable.

       static void Main(string[] args)
        {
            DataTable dt = new DataTable();
            dt.Columns.Add("Col A", typeof(int));
            dt.Columns.Add("Col B", typeof(string));
            dt.Columns.Add("Col C", typeof(int));
            dt.Columns.Add("Col D", typeof(string));
            dt.Columns.Add("Col E", typeof(int));
            dt.Columns.Add("Col F", typeof(string));
            dt.Columns.Add("Col G", typeof(int));
            dt.Columns.Add("Col H", typeof(string));
            dt.Columns.Add("Col I", typeof(int));
            dt.Columns.Add("Col J", typeof(string));

            DateTime begin = DateTime.Now;

            for (int i = 0; i < 7500; i++)
            {
                dt.Rows.Add(new object[] {
                    i + 10000, "b", i + 20000, "d", i + 30000, "f", i + 40000, "h", i + 50000, "i"
                });
            }

            DateTime end = DateTime.Now;

            Console.WriteLine((end - begin).ToString());

            Console.ReadLine();
        }


Лицензировано согласно: CC-BY-SA with attribution
Не связан с Stack Overflow
Лицензировано согласно: CC-BY-SA with attribution
Не связан с Stack Overflow