Ошибка – транзакция, связанная с текущим соединением, завершена, но не была удалена

У меня возникли проблемы с использованием TransactionScope для переноса нескольких запросов к базе данных в транзакцию. Я использую SqlBulkCopy с batchsize 500. Когда я увеличил размер партии до 1000, я получаю ошибку:

Транзакция, связанная с текущим соединением, завершена, но не была удалена. Транзакция должна быть удалена до того, как соединение будет использоваться для выполнения операторов SQL.

Это код, который я использую:

 using (var scope = new TransactionScope()) { using (var connection = (SqlConnection)customerTable.OpenConnection()) { var table1BulkCopy = new SqlBulkCopy(connection) { BatchSize = BATCH_SIZE, DestinationTableName = TableName1 }; table1BulkCopy.WriteToServer(table1DataTable); var table2BulkCopy = new SqlBulkCopy(connection) { BatchSize = BATCH_SIZE, DestinationTableName = TableName2 }; table2BulkCopy.WriteToServer(table2DataTable); var table3BulkCopy = new SqlBulkCopy(connection) { BatchSize = BATCH_SIZE, DestinationTableName = TableName3 }; table1BulkCopy.WriteToServer(table3DataTable); var table4BulkCopy = new SqlBulkCopy(connection) { BatchSize = BATCH_SIZE, DestinationTableName = TableName4 }; table4BulkCopy.WriteToServer(table4DataTable); scope.Complete(); } } 

Это может произойти, когда транзакция истечет. Вы можете увеличить таймаут для своей транзакции, как это (используйте значения, соответствующие ожидаемой длине вашей транзакции). Код ниже составляет 15 минут:

 using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required, new System.TimeSpan(0, 15, 0))) { // working code here } 

Вот почему он мог бы работать для batchsize 500, а не для 1000.

Я обнаружил, что установка тайм-аута в TransactionScope не работает для меня. Мне также необходимо было добавить следующий ключ конфигурации в конец machine.config чтобы пропустить максимальный тайм-аут по умолчанию 10 минут.

     

Кредит: http://thecodesaysitall.blogspot.com.au/2012/04/long-running-systemtransactions.html

Переместить scope.Complete(); вне connection блока.

 using (var scope = new TransactionScope()) { using (var connection = (SqlConnection)customerTable.OpenConnection()) { // } scope.Complete(); } 

Полный ответ должен быть более полным.

Необходимо указать – где будет установлен максимальный таймаут транзакции – в .Net-коде или в конфигурации сервера

  

В этом случае вы можете установить максимальное время ожидания в файле machine.config

      

Или, возможно, вы хотите переопределить это поведение в приложении. Затем в machine.config вы должны установить атрибут velue:

 ...allowDefinition="MachineToApplication" 

Это хорошая статья: https://blogs.msdn.microsoft.com/ajit/2008/06/18/override-the-system-transactions-default-timeout-of-10-minutes-in-the-code/

Довольно очевидная проблема с тайм-аутом, но вы не получите эффекта, если вы установили TransactionOptions.Timeout выше. Даже если вы установите TimeSpan.MaxValue, вы фактически не получите прибыль. Не имеет значения, что свойство Timeout для TransactionOptions установлено на более высокое значение, TransactionOptions.Timeout не может превышать свойство maxTimeout. Вы должны настроить некоторые изменения в файле machine.config .

Вскоре вы должны найти файл machine.config% windir% \ Microsoft.NET \ Framework \ yourversion \ config \ machine.config
И добавьте это в :

    

Здесь вы можете установить свойство maxTimeout на 30 минут.
Подробнее см. Ниже: http://thecodesaysitall.blogspot.com/2012/04/long-running-systemtransactions.html