2013-04-18 18 views
5

Betrachten Sie die folgenden Methoden.Wird TransactionScope implizit angewendet, bis explizit Completed?

DoA() 
{ 
    using (TransactionScope scope = new TransactionScope) 
    { 
    using (SqlConnection connection = new SqlConnection(connectionString)) 
    { 
     connection.Open(); 
     SqlCommand command = new SqlCommand(query, connection); 
     command.ExecuteNonReader(); 

     DoB();  

     scope.Complete(); 
    } 
    } 
} 

DoB() 
{ 
    using (TransactionScope scope = new TransactionScope) 
    { 
    using (SqlConnection connection = new SqlConnection(connectionString)) 
    { 
     connection.Open(); 
     SqlCommand command = new SqlCommand(query, connection); 
     command.ExecuteNonReader(); 

     DoC(); 

     scope.Complete(); 
    } 
    } 
} 

DoC() 
{ 
    using (SqlConnection connection = new SqlConnection(connectionString)) 
    { 
    connection.Open(); 
    SqlCommand command = new SqlCommand(query, connection); 
    command.ExecuteNonReader(); 
    } 
} 

Wenn wir DoA() nennen, tun die nachfolgenden Interaktionen in DoB() und DoC() Lauf im Rahmen der DoA() ‚s Transaktion, wie es zu SQL Server gehört? Wird DoC() im Kontext der Transaktionen DoA() und DoB() ausgeführt?

(Oder bin ich grob Mißverständnis etwas?)

+1

Sie erhalten verschachtelte Transaktionen :) – DaveShaw

+0

Es gibt Optionen, die dies steuern. Siehe "Verwalten des Transaktionsflusses mithilfe von TransactionScopeOption" von http://msdn.microsoft.com/en-us/library/ms172152(v=vs.85).aspx – AaronLS

+0

Hinweis: Weitere Anmerkungen zu verschachtelten Transaktionen müssen dieselbe Isolationsstufe verwenden an der Ambient-Transaktion teilnehmen. – AaronLS

Antwort

4

Der gesamte Code wird logisch eine einzige Transaktion sein. Die verschachtelten Bereiche erstellen nicht unbedingt eine neue Transaktion (es sei denn, Sie verwenden RequiresNew), sodass es sich um eine einzelne Transaktion handelt. Jetzt muss jeder Bereich abstimmen, um die Transaktion abzuschließen, sodass in Ihrem zweiten Bereich, wenn Sie die Complete entfernen, die Rollback der gesamten Transaktion verursachen sollte.

DoC wird ebenfalls Teil der Transaktion sein; Die Ambient-Transaktion erkennt die neue Verbindung und wird automatisch eingetragen.

Bitte alle Details lesen here, die das Verhalten der Einschreibung in der Ambient-Transaktion und die verschiedenen Optionen Requires, RequiresNew und Suppress erklären.

Beachten Sie auch, dass, wenn Ihre Verbindungen nicht GENAU dieselbe Verbindungszeichenfolge verwenden, wird die gesamte Transaktion automatisch zu einer verteilten Transaktion heraufgestuft. Nur etwas, auf das man achten sollte.

+0

+1 Gute Info. Bevor ich akzeptiere, können Sie einfach bestätigen, dass 'DoC()' in der Ambient 'Transaction' von' DoA() 'und/oder' DoB() 'ausgeführt wird? (Was ich erwarte * und * denke * passiert - aber ich will sicher sein.) – svidgen

+0

@svidgen Meine Antwort wurde aktualisiert. – Andy

+0

Schön. Vielen Dank! – svidgen

2

Herausgegeben pro Andys Kommentare:

Es scheint, als ob so etwas wie dies auf dem SQL-Server auftreten würde:

BEGIN TRANSACTION A 

    -- do A's work 

    -- B does NOT create a new transaction 

    -- do B's work 

    -- do C's work 

COMMIT TRANSACTION A 

Die folgenden Ereignisse eintritt wenn new TransactionScope(TransactionScopeOption.RequiresNew) in DoB() verwendet wird.

BEGIN TRANSACTION A 

    -- do A's work 

    BEING TRANSACTION B 

    -- do B's work 

    -- do C's work 

    COMMIT TRANSACTION B 
COMMIT TRANSACTION A 
+0

Das wird nicht passieren; Es wird eine einzelne Transaktion sein, da der in B verwendete Bereich der bestehenden Ambient-Transaktion beitritt. Wenn B nicht für "Complete" abstimmt, wird die gesamte Transaktion zurückgesetzt. – Andy

+0

@Andy Danke für die Klarstellung. Wird das passieren, wenn stattdessen 'new TransactionScope (TransactionScopeOptions.RequiresNew)' verwendet wird? – svidgen

+0

@Andy Nevermind, sah nur deine Antwort! – svidgen