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

У меня возникли проблемы с использованием 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();
    }
}

Ответ 1

Я знаю, что это поздно, но, возможно, это поможет кому-то другому.

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

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

Вот почему он мог работать в batchsize 500, а не на 1000.

Ответ 2

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

<system.transactions>
    <machineSettings maxTimeout="00:30:00" /> <!-- 30 minutes -->
</system.transactions>

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

Ответ 3

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

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