Weder die TransactionScope
noch unterstützt SQL Server verschachtelte Transaktionen.
Sie können verschachteln TransactionScope
Instanzen, aber das hat nur den äußeren Anschein einer verschachtelten Transaktion. In Wirklichkeit handelt es sich um eine so genannte "umgebende" Transaktion, und es kann immer nur eine geben. Welche Transaktion die umgebende Transaktion ist, hängt davon ab, was Sie für TransactionScopeOption
wenn Sie den Bereich erstellen.
Zur näheren Erläuterung sei Folgendes angeführt:
using (var outer = new TransactionScope())
{
DoOuterWork();
using (var inner1 = new TransactionScope(TransactionScopeOption.Suppress))
{
DoWork1();
inner1.Complete();
}
using (var inner2 = new TransactionScope(TransactionScopeOption.RequiresNew))
{
DoWork2();
inner2.Complete();
}
using (var inner3 = new TransactionScope(TransactionScopeOption.Required))
{
DoWork3();
inner3.Complete();
}
outer.Complete();
}
Im Folgenden wird beschrieben, was bei den einzelnen inneren Bereichen geschieht:
-
inner1
wird in einer impliziten Transaktion ausgeführt, unabhängig von outer
. Nichts, was in der DoWork1
ist garantiert atomar. Wenn dies auf halbem Weg scheitert, haben Sie inkonsistente Daten. Jede Arbeit, die hier stattfindet, wird immer übertragen, unabhängig davon, was mit outer
.
-
inner2
wird in einer neuen Transaktion ausgeführt, unabhängig von outer
. Dies ist eine verschiedene Transaktion von outer
aber es ist no verschachtelt. Schlägt es fehl, wird die Arbeit, die in outer
( DoOuterWork()
) und jeder der anderen Bereiche kann immer noch begangen werden, aber hier ist der Haken: Wenn dies der Fall ist, wird die gesamte outer
Transaktion wird no die im Inneren geleistete Arbeit rückgängig machen inner2
. Aus diesem Grund ist sie nicht wirklich verschachtelt. Auch, inner2
hat keinen Zugriff auf Zeilen, die von outer
Wenn Sie also nicht aufpassen, kann es hier zu Deadlocks kommen.
-
inner3
wird in der dieselbe Transaktion als outer
. Dies ist das Standardverhalten. Wenn DoWork3()
scheitert und inner3
nie abgeschlossen wird, dann wird die gesamte outer
Transaktion wird zurückgenommen. Ähnlich verhält es sich, wenn inner3
wird erfolgreich abgeschlossen, aber outer
rückgängig gemacht wird, dann wird jede Arbeit, die in DoWork3()
wird ebenfalls rückgängig gemacht.
Sie können also hoffentlich sehen, dass keine dieser Optionen tatsächlich verschachtelt ist und Ihnen nicht das gibt, was Sie wollen. Die Required
ähnelt einer verschachtelten Transaktion, gibt Ihnen aber nicht die Möglichkeit, bestimmte Arbeitseinheiten innerhalb der Transaktion unabhängig voneinander zu übertragen oder zurückzusetzen.
Das, was einer echten verschachtelten Transaktion in SQL Server am nächsten kommt, ist die SAVE TRAN
Anweisung kombiniert mit einigen TRY/CATCH
Blöcke. Wenn Sie Ihre Logik in einer oder mehreren Stored Procedures unterbringen können, wäre dies eine gute Option.
Andernfalls müssen Sie, wie von Oded vorgeschlagen, für jede Rechnung separate Transaktionen verwenden.