Получение SqlBulkCopy для учета имен столбцов - PullRequest
18 голосов
/ 23 августа 2011

Я нахожусь в процессе преобразования некоторых подпрограмм на основе хранимых процедур для запуска в C #. Общая идея состоит в том, чтобы использовать все чудеса C # / .NET Framework, а затем отправить результаты обратно в БД. Все шло гладко, кроме одной проблемы, с которой я столкнулся вчера и решил сегодня.

Чтобы выполнить импорт, я программно создаю DataTable и использую SqlBulkCopy для перемещения результатов на сервер.

, например

 DataTable detail = new DataTable();
 detail.Columns.Add(new DataColumn("Stock", Type.GetType("System.Decimal")));
 detail.Columns.Add(new DataColumn("Receipts", Type.GetType("System.Decimal")));
 detail.Columns.Add(new DataColumn("Orders", Type.GetType("System.Decimal")));

В таблице импорта были поля в следующем порядке.

...
Stock decimal(18,4),
Orders decimal(18,4),
Receipts decimal(18,4)
...

По сути, значение для поступлений переходило в заказы, и наоборот.

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

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

Это серьезно мешает моему решению. Теперь это только таблицы импорта, поэтому при необходимости я могу удалить их и создать заново как часть любого сценария миграции с неизменными порядковыми позициями. Я бы предпочел этого не делать.

Есть ли способ заставить SqlBulkCopy учитывать имена столбцов, которые вы указали заполнить?

Ответы [ 7 ]

18 голосов
/ 15 октября 2015

Вот решение, чтобы исправить эту «ошибку».

По умолчанию это отображение по порядковому номеру / положению.

В моем случае я загружал из таблицы с столбцами в случайном порядке,вот быстрое исправление (таблица - это моя DataTable, которая «не в порядковом порядке», а bulkCopy - это объект SqLBulkCopy)

foreach (DataColumn col in table.Columns)
{
    bulkCopy.ColumnMappings.Add(col.ColumnName, col.ColumnName);
}

Как видите, я просто заставляю его переупорядочиватьимя, даже если имена ИДЕНТИЧНЫЕ.

16 голосов
/ 23 августа 2011

С http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlbulkcopy.columnmappings.aspx:

Однако, если количество столбцов отличается или порядковые позиции не согласованы, необходимо использовать ColumnMappings, чтобы убедиться, что данные копируются в правильные столбцы.

Пример кода см. В разделе «Отображение столбцов» в http://www.sqlteam.com/article/use-sqlbulkcopy-to-quickly-load-data-from-your-client-to-sql-server

.
1 голос
/ 24 августа 2011

В параметрах проекта есть опция сравнения SQL в Force Force Order Order. Это сгенерирует скрипт, который будет переупорядочивать столбцы. Я могу ошибаться, но я думаю, что эта операция может потребовать перестроения таблицы, поэтому, пожалуйста, используйте ее с осторожностью, так как это может повлиять на производительность. Однако скрипт сохранит данные таблицы.

0 голосов
/ 10 июля 2018

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

using (SqlBulkCopy bulkcopy = new SqlBulkCopy(dc.ConnectionString))
{
        bulkcopy.BulkCopyTimeout = 150; 

        // column mapping defined
        dt.Columns.Cast<DataColumn>().ToList().ForEach(f =>
        {
            SqlBulkCopyColumnMapping bccm = new SqlBulkCopyColumnMapping();
            bccm.DestinationColumn = f.ColumnName;
            bccm.SourceColumn = f.ColumnName;
            bulkcopy.ColumnMappings.Add(bccm);
         });
        // column mapping defined

         bulkcopy.DestinationTableName = outputTable;
         bulkcopy.WriteToServer(dt);

}
0 голосов
/ 06 июля 2018

Вот Гист с методом расширения для него .

Пример:

bulkCopy
    .WithColumnMappings(table.Columns)
    .WriteToServer(table);

Это очищает существующие сопоставления столбцов, а затем добавляет сопоставление для каждого переданного столбца.

0 голосов
/ 23 августа 2011

Я могу что-то упустить, но почему вы не можете изменить порядок своих столбцов? Я обычно не строю свой DataTable вручную. Я использую FillSchema метод SqlDataAdapter, используя "select * from targetTable" запрос. Поэтому я всегда уверен, что мой DataTable соответствует целевой таблице.

0 голосов
/ 23 августа 2011

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

Извлечь SqlBulkCopyColumnMappingCollection.Add и установить SqlBulkCopy.ColumnMappings собственность.

...