Можно ли использовать System.Transactions.TransactionScope с SqlBulkCopy? - PullRequest
32 голосов
/ 06 сентября 2011

Очень простой вопрос: можно ли использовать System.Transactions.TransactionScope вместе с SqlBulkCopy?В документации Операции транзакции и массового копирования ничего не упоминается (по крайней мере, в .NET 4.0), и мое тестирование показывает, что оно не подключается автоматически с TransactionScope.

Ответы [ 3 ]

36 голосов
/ 24 октября 2015

SqlBulkCopy никогда не зачисляется в транзакцию.SqlCommand также не делает этого.Распространенное заблуждение.Зачисление выполняется во время вызова SqlConnection.Open.После этого все, что выполняется в этом соединении, является частью транзакции неявно.На самом деле не разрешено передавать явную транзакцию.

Если вы хотите, чтобы SqlBulkCopy принял участие в System.Transactions.Transaction с использованием TransactionScope, транзакция должна быть установлена ​​наКогда вы открываете соединение.

Это очень легко сделать:

using (var tran = new TransactionScope(...))
using (var conn = new SqlConnection(connStr))
{
  conn.Open(); //This enlists.

  using (var sqlBulkCopy = new SqlBulkCopy(conn)) {
    sqlBulkCopy.WriteToServer(...);
  }

  tran.Complete(); //Commit.
}

Этот код - все, что вам нужно.Возможные ошибки:

  1. Транзакция должна быть открыта достаточно рано.
  2. Не используйте параметр SqlTransaction SqlBulkCopy.Pass null.
  3. Не используйте SqlBulkCopyOptions.UseInternalTransaction.
  4. Не добавляйте обработку исключений, если вы действительно не хотите что-то делать.Откат происходит автоматически, если нет фиксации.
  5. Используйте оператор using для очистки кода и детерминированной очистки.Не закрывайте и не утилизируйте эти объекты вручную, если это не необходимо.Это будет избыточно.

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

4 голосов
/ 01 января 2013

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

  1. Создайте SqlConnection с сервером базы данных назначения.
  2. Открыть соединение.
  3. Создать объект SqlTransaction.
  4. Создание объекта SqlBulkCopy, передаваемого в объект SqlTransaction в конструктор.
  5. Выполните импорт - вызов WriteToServer - в течение Попробуй ... Поймай блок. Если операция завершена, зафиксируйте транзакцию; если не получится, отбросьте его назад.

Использование транзакций с SqlBulkCopy

3 голосов
/ 06 сентября 2011

Единственный способ определить транзакцию в массовой загрузке (насколько мне известно) - указать размер пакета.

Преимущество массовой загрузки заключается в том, что вы получаете блокировку массового обновления (многопоточное чтение и многопоточное чтение).Вы получаете это, когда используете bcp, массовую вставку, задачу потока данных ssis с (таблок), вставку (столбцы), выбираете столбцы из openrowset (массовая) или sqlbulkcopy.Это удобно при попытке минимизировать как время загрузки, так и размер журнала транзакций (только если вы выполнили минимально зарегистрированные требования, что сэкономит вам часы на миллионах строк).

Каждый раз, когда вы загружаете данные,журнал транзакций станет узким местом.Если время имеет существенное значение, важно свести к минимуму количество регистрируемых файлов.

Как только размер пакета будет удовлетворен (количество строк, которое вы указали для фиксации), транзакция будет зафиксирована и начнется заново.Если вы укажете размер пакета 0, транзакция будет охватывать весь файл и выполнять откат при возникновении проблем с данными.

...