2014-01-23 10 views
6

Wenn TransactionScope verwendet wird, wird angezeigt, dass, wenn intern Code ausgeführt wird, die Transaktion rückgängig gemacht wird, da die übergeordnete Transaktion ebenfalls zurückgesetzt wird. Was ist gut für mich. Wenn dieser Bereich jedoch freigegeben wird, wird eine Ausnahme ausgelöst, was bedeutet, dass die Transaktion bereits zurückgesetzt wurde und abgebrochen wurde. Also, was ist der richtige Weg, um damit umzugehen und den Bereich richtig zu entsorgen?TransactionScope hat die Transaktion vor dem Verkauf abgebrochen

using (TransactionScope scope = new TransactionScope(TransactionScopeOption.RequiresNew)) 
    { 
        using (var conn = GetConnection()) 
        { 
          string query = 
       @"some query that may contain transaction itself 
       or some SP whith transaction included" 

          using (var command = new SqlCommand(query, conn)) 
           command.ExecuteNonQuery(); 
         } 
        } 
        scope.Complete(); 
    } // Exception here 

Antwort

6

scope.Dispose()TransactionAborted Ausnahme auslösen kann, auch wenn scope.Complete() aufgerufen wurde. Zum Beispiel einige gespeicherte Prozeduren eine schlau genug, um Ausnahmen zu behandeln und Transaktion innerhalb T-SQL-Skript mit T-SQL TRY/CATCH Konstrukt w/o Wurf Ausnahme für den Aufrufer abzubrechen. Also ich würde die sicherste Ansatz halte ich vorschlagen würde, ist wie folgt:

try 
{ 
    using (TransactionScope scope = new TransactionScope(TransactionScopeOption.RequiresNew)) 
    { 
     try 
     { 
      using (var conn = GetConnection()) 
      { 
       string query = 
       @"some query that may contain transaction itself 
       or some SP whith transaction included" 

       using (var command = new SqlCommand(query, conn)) 
       command.ExecuteNonQuery(); 
      } 
     } 
     catch (SqlException ex) 
     { 
      // log SQL Exception, if any 
      throw; // re-throw exception 
     } 

     scope.Complete(); 
    } 
} 
catch (TransactionAbortedException ex) 
{ 
    // we can get here even if scope.Complete() was called. 
    // log TransactionAborted exception if necessary 
} 

Und keine Sorge über TransactionScope entsorgen. scope.Dispose führt alles aus, was nötig ist, um es zu bereinigen, bevor es die TransactionAborted Ausnahme auslöst.

0

Wenn eine Ausnahme von Ihrer inneren Abfrage ausgelöst wird, wird die scope.Complete() Zeile nicht ausgeführt. Bitte beachten Sie den unten stehenden Link .. Und ich habe auch einige Änderungen an Ihrer Abfrage vorgenommen. Ich hoffe, es sollte für dich funktionieren. Transaction Scope

using (TransactionScope scope = new TransactionScope(TransactionScopeOption.RequiresNew)) 
{ 
    using (var conn = GetConnection()) 
    { 
     string query = 
     @"some query that may contain transaction itself 
     or some SP whith transaction included" 

     using (var command = new SqlCommand(query, conn)) 
     command.ExecuteNonQuery(); 
    } 
    scope.Complete(); 
} 
0

Ich verwende keine gespeicherten Procs oder SQL-spezifische try/catch, also meine Situation war etwas anders, aber ich habe genau die gleiche Transaktion abgebrochen Ausnahme erwähnt in der Post. Ich habe festgestellt, dass, wenn ich irgendwo innerhalb des primären TransactionScopes eine SELECT-Anweisung habe, die Transaktion zum Commit führen wird, obwohl ich mir nicht sicher bin, warum. Ich hatte einen Fall, in dem, um ein Objekt in der Datenbank zu erstellen, zuerst überprüft wurde, ob das Objekt bereits mit einem SELECT existierte, und dann die Abbruchausnahme auftrat, als Dispose aufgerufen wurde. Ich schaute auf die Inner Exception und sagte, die Transaktion habe versucht, ohne einen Anfang zu begehen. Ich habe schließlich versucht, meine SELECT in einem Supported TransactionScope zu verpacken, und dann hat es funktioniert. Also:

Ich hoffe, dass dies jemand anderen hilft, die diese Ausnahme erhalten haben könnte, ohne gespeicherte Procs.

Verwandte Themen