Помогите, пожалуйста, найти оптимальный вариант решения такой задачи.
Дано:
1) Типизированный DataSet: Table1(ID(PK, identity), Name), Table1DataAdapter
2) Данные в DataSet загружаются из xml-файла, после загрузки Table1RowState = Added
Необходимо:
Записать эти данные в таблицу БД с сохранением значений ID (т.е. отключить identity (это-то мы умеем, только TableAdapter сгенерирован с учетом того, что ID вставляться не будет))
Более высокоуровневая задача звучит так: Обеспечить загрузку новых справочников в БД филиала из xml-файла (с сохранением ID, чтобы последующая передача документов в центр из филиала не повлекла передачи справочников)
P.S.: Циклов делать не хочется что-то и внешние библиотеки тоже не хочется применять (SMO, SSIS)
данное сообщение получено с www.gotdotnet.ru
ссылка на оригинальное сообщение
Может вам подойдёт System.Data.SqlClient.SqlBulkCopy?
данное сообщение получено с www.gotdotnet.ru
ссылка на оригинальное сообщение
Если циклов не хочется, создайте DataAdapter, который вставляет все столбцы. Можно даже не мучиться с дизайнерами, а создать такой объект прямо в коде.
данное сообщение получено с www.gotdotnet.ru
ссылка на оригинальное сообщение
2 Lelikeks:
>> ...создайте DataAdapter, который вставляет все столбцы...
Вопрос: А для этого DataAdapter'а нужно будет прописывать UpdateCommand, InsertCommand? Это же нужно прописывать все столбцы, параметры, так?
данное сообщение получено с www.gotdotnet.ru
ссылка на оригинальное сообщение
2 k_savelev:
Спасибо, не знал о таком классе.
Попробовал использовать — не получилось так как надо.
1)
DELETE FROM TableName
2)
SET IDENTITY_INSERT TableName ON
3)
Using bcp As New SqlBulkCopy(Package.Connection)
bcp.DestinationTableName = TableName
Table.Columns("ID").AutoIncrement = False
Table.Columns("ID").ReadOnly = False
bcp.WriteToServer(Table)
End Using
4)
SET IDENTITY_INSERT TableName OFF
Получаю сообщение на Exception:
Explicit value must be specified for identity column in table 'sprSysProf' either when IDENTITY_INSERT is set to ON or when a replication user is inserting into a NOT FOR REPLICATION identity column.
Если убрать IDENTITY у поля в таблице, то шаги 1, 3 проходят. Но такой вариант не подходит, потому что:
1) Необходимо убирать IDENTITY у всех таблиц;
2) Необходима делать транзакцию, иначе пользователь может остаться без данных после шага 1.
Попробую конкретизировать вопросы:
1) Возможно ли смешивать T-SQL и Bulk-команды в пределах одной транзакции?
2) Возможно ли сделать такой Bulk INSERT, который будет удалять уже имеющиеся записи перед вставкой?
данное сообщение получено с www.gotdotnet.ru
ссылка на оригинальное сообщение
Возможно поможет MSDN:
Performing a Bulk Copy Operation in a Transaction
И SqlBulkCopyOptions.KeepIdentityy
данное сообщение получено с www.gotdotnet.ru
ссылка на оригинальное сообщение
Большое спасибо!
Все работает как надо!!
Try
Package.Connection.Open()
Using transaction As SqlTransaction = Package.Connection.BeginTransaction()
Try
DeleteCommand.Transaction = transaction
DeleteCommand.Connection = Package.Connection
DeleteCommand.ExecuteNonQuery()
Using bcp As New SqlBulkCopy(Package.Connection, SqlBulkCopyOptions.KeepIdentity, transaction)
bcp.DestinationTableName = TableName
bcp.WriteToServer(Table)
End Using
transaction.Commit()
Catch ex As Exception
transaction.Rollback()
Throw New Exception("Ошибка загрузки таблицы """ & TableName & """", ex)
End Try
End Using
Finally
Package.Connection.Close()
End Try
данное сообщение получено с www.gotdotnet.ru
ссылка на оригинальное сообщение
может оказаться полезным в более общем случае сценарий, который использовался для реализации "репликации"
имеется два соединения
в первом:
создается глобальная временная таблица с без признака identity для полей
в нее заливаются данные
во втором вызывается хранимая процедура выполняющая следующие действия
update существующих записей (у нас была возможность знать есть ли изменения)
insert несуществующих записей
разумеется, что была обработка уникальных индексов и других возможных проблем
такой подход не требовал внешней транзакции, и работа пользователя практически не прерывалась (меньшая длительность блокировок)