Получение SqlBulkCopy для оценки имен столбцов

Я пытаюсь преобразовать некоторые процедуры отчетности, основанные на хранимых процедурах, для работы на С#. Общая идея заключается в том, чтобы использовать все чудеса С#/.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)
...

По существу, значение квитанций поступало в Orders, и наоборот.

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

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

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

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

Ответы

Ответ 1

Из 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

Ответ 2

Вот решение для исправления этой "ошибки".

По умолчанию используется карта по порядку/позиции.

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

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

Как вы можете видеть, я просто заставляю его переупорядочивать по имени, хотя имена имеют IDENTICAL.

Ответ 3

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

Ответ 4

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

Отметьте SqlBulkCopyColumnMappingCollection.Add и установите SqlBulkCopy.ColumnMappings.

Ответ 5

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