2012-07-12 41 views
46

He estado teniendo problemas al usar el TransactionScope para envolver varias consultas de bases de datos en una transacción, estoy usando SqlBulkCopy con batchsize 500. Cuando aumente el lote tamaño a 1000 estoy consiguiendo el error:Error: la transacción asociada con la conexión actual se ha completado pero no se ha eliminado

The transaction associated with the current connection has completed but has not been disposed. The transaction must be disposed before the connection can be used to execute SQL statements.

Este es el código que estoy utilizando:

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(); 
    } 
} 

Respuesta

7

Mover scope.Complete(); fuera del bloque connection.

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

Aquí más información ¿Por qué? Es una muy buena práctica colocar la llamada como la última instrucción en el bloque de uso. [Más información sobre el método] (https://msdn.microsoft.com/es-es/library/system.transactions.transactionscope.complete (v = vs.110) .aspx) – Angel

+1

Ayudó. Gracias a allot –

85

Sé que es tarde, pero quizás ayudará a otra persona.

Esto puede suceder cuando la transacción expira. Puede aumentar el tiempo de espera para su transacción de esta manera (use los valores apropiados para la duración esperada de su transacción). El código siguiente es de 15 minutos:

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

Es por esto que podría haber trabajado para batchsize 500 y no para 1000.

+0

Estoy obteniendo esto con 'Timeout = TransactionManger.MaximumTimeout', así que esta no es la única forma en que este error puede ocurrir. –

+0

Esta respuesta solucionó un problema que estaba teniendo. como @Eric J mencionó que no es la única forma en que este error puede ocurrir, pero si se agota el tiempo de espera de la transacción, se obtiene el mensaje no relacionado anteriormente. – b0redom

+0

@Pradeep esta es la respuesta correcta y debe marcarse como tal. – Kiquenet

17

He encontrado que la fijación del tiempo de espera en el TransactionScope no funcionó para mí. También necesitaba agregar la siguiente clave de configuración al final de la etiqueta machine.config <configuration> para extender el tiempo máximo predeterminado de 10 minutos.

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

Crédito: http://thecodesaysitall.blogspot.com.au/2012/04/long-running-systemtransactions.html

+0

Tenga en cuenta que * debe * poner esto en el * final * de la sección de configuración, de lo contrario recibirá un error de IIS. –

0

La respuesta completa debe ser más completa.

Debe especificar - en el que se espera de transacción máximo determinado - en el código .Net, o en la configuración del servidor

<sectionGroup name="system.transactions".... 
    ...allowDefinition="MachineOnly" 
</sectionGroup> 

En este caso se puede establecer el tiempo de espera máximo en el machine.config

<configuration> 
<system.transactions> 
<machineSettings maxTimeout="01:00:00" /> 
</system.transactions> 
</configuration> 

O puede ser que desee anular este comportamiento en la aplicación. Entonces en el machine.config debe establecer el atributo velue:

...allowDefinition="MachineToApplication" 

Ésta es una buena arcticle: https://blogs.msdn.microsoft.com/ajit/2008/06/18/override-the-system-transactions-default-timeout-of-10-minutes-in-the-code/

Cuestiones relacionadas