Подтвердить что ты не робот

Можно ли использовать System.Transactions.TransactionScope с SqlBulkCopy?

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

4b9b3361

Ответ 1

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.
}

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

  • Сделка должна быть открыта достаточно рано.
  • Не используйте параметр SqlTransaction SqlBulkCopy. Пропустить null.
  • Не используйте SqlBulkCopyOptions.UseInternalTransaction.
  • Не добавляйте обработку исключений, если вы действительно не хотите что-то делать. Откат автоматически, если нет фиксации.
  • Используйте инструкцию using для чистого кода и детерминированной очистки. Не закрывайте вручную или не удаляйте какие-либо из этих объектов, если это необходимо. Это было бы лишним.

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

Ответ 2

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

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

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

Ответ 3

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

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

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

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

Ответ 4

дополнительный способ можно использовать для минимизации времени блокировки в реальной жизни


use SqlBulkCopy and copy data to temporary table use delete output construction to move data into production table