2012-07-12 18 views
46

Mam problemy z użyciem TransactionScope do zawijania wielu zapytań do bazy danych do transakcji, używam SqlBulkCopy z wsadką 500. Gdy zwiększyłem partię wielkość do 1000 otrzymuję błąd:Błąd - transakcja powiązana z bieżącym połączeniem została zakończona, ale nie została usunięta.

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.

jest to kod używam:

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

Odpowiedz

7

Move scope.Complete(); zewnątrz bloku connection.

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

Tutaj więcej informacji, dlaczego? Bardzo dobrą praktyką jest umieszczenie wywołania jako ostatniej instrukcji w bloku użytym. [Więcej informacji o metodzie] (https://msdn.microsoft.com/es-es/library/system.transactions.transactionscope.complete (v = vs.110) .aspx) – Angel

+1

Pomogło. Dziękuję allot –

85

Wiem, że jest późno, ale być może pomoże to komuś innemu.

Może się to zdarzyć, gdy upłynie limit czasu transakcji. Możesz zwiększyć limit czasu dla transakcji w ten sposób (użyj wartości odpowiednich dla oczekiwanej długości transakcji). Poniższy kod jest przez 15 minut:

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

To dlatego, że nie mogło pracował batchsize 500, a nie za 1000.

+0

Otrzymuję to z 'Timeout = TransactionManger.MaximumTimeout', więc nie jest to jedyny sposób, w jaki ten błąd może wystąpić. –

+0

Ta odpowiedź naprawiła problem, który miałem. ponieważ @Eric J wspomniał, że nie jest to jedyny sposób, w jaki ten błąd może wystąpić, ale jeśli Twoja transakcja przekroczy limit czasu, otrzymasz raczej niepowiązany komunikat powyżej. – b0redom

+0

@Pradeep to jest odpowiednia odpowiedź i powinna być oznaczona jako tak. – Kiquenet

17

Okazało się, że ustawienie limitu czasu w TransactionScope nie działa dla mnie. Potrzebowałem również dodać następujący klucz konfiguracyjny na końcu znacznika machine.config <configuration>, aby przekroczyć domyślny limit czasu wynoszący 10 minut.

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

kredytowe: http://thecodesaysitall.blogspot.com.au/2012/04/long-running-systemtransactions.html

+0

Pamiętaj, że * musisz * umieścić to na * końcu * sekcji konfiguracji, w przeciwnym razie pojawi się błąd z IIS. –

0

Pełną odpowiedź musi być bardziej pełny.

Musisz podać - gdzie będzie max Timeout transakcja określona - w kodzie .NET lub w config serwera

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

W tym przypadku można ustawić maksymalny czas oczekiwania w machine.config

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

A może chcesz zastąpić to behaivor w aplikacji. Następnie w machine.config należy ustawić atribute na velue:

...allowDefinition="MachineToApplication" 

Jest to dobry arcticle: https://blogs.msdn.microsoft.com/ajit/2008/06/18/override-the-system-transactions-default-timeout-of-10-minutes-in-the-code/

Powiązane problemy