Verschachtelte Transaktionen mit netTiers C#

Vor einiger Zeit hatte ich in diesem Beitrag beschrieben wie man Transaktionen mit netTiers verwenden kann. In diesem Beitrag nun möchte ich eine weiter fortgeschrittene Technik zeigen mit welcher man die Transaktion auch in verschachtelten und rekursiven Methoden verwenden kann.

Hintergrund

Obwohl es keine „echten“ verschachtelten Transaktionen sind, habe ich die Überschrift so gewählt, da das Ergebnis dem von verschachtelten Transaktionen gleicht.

Der nachfolgende Beitrag erläutert die notwendigen zusätzlichen Vorkehrungen die man treffen muss um Transaktionen in verschachtelten und rekursiven Methodenaufrufen zu verwenden.

Lösungsansatz

Um Transaktionen in verschachtelten Aufrufen verwenden zu können, ist es notwendig festzustellen, ob bereits eine Transaktion vorhanden ist und ob diese geöffnet (BeginTransaktion) ist.

Gibt es eine aktive (äussere) Transaktion, so ist innerhalb der geschachtelten Methode dafür zu sorgen, dass keine lokale Transaktion erzeugt wird, bzw. dass keine globalen Methoden Aufrufe (wie Commit und Rollback) der Transaktion aufgerufen werden (Die Transaktion gehört der aufrufenden Methode, die sich darum kümmern muss ob ein Commit oder Rollback gemacht wird).

Lösung – Erweiterte Version mit localTransaction

int retval = 0;    // Definieren einer int variablen die einen Rückgabewert der Methode aufnehmen kann.
bool localTransaction = false;    // Flag welches verwendet wird um die Verwendung eine lokalen Transaktion zu signalisieren

if (ConnectionScope.Current.TransactionManager == null)
{
ConnectionScope.Current.TransactionManager = ConnectionScope.CreateTransaction();
localTransaction = true;    // Es gab keine äussere Transaktion also haben wir eine lokale erstellt und auch gleich geöffnet (impliziter Aufruf von BeginTransaction)
}
TransactionManager tm = ConnectionScope.Current.TransactionManager;
if (!tm.IsOpen)  // jetzt prüfen ob auch eine geöffnete Transaktion vorhanden ist (wenn nicht, dann eine lokale Transaktion aufmachen)
{
tm.BeginTransaction();
localTransaction = true;
}

// Hier nun der eigentlich Code
// Wenn alle Datenbankoperationen durchgeführt werden konnten, wird 0 zurückgegeben, sonst ein int Wert aus dem die Aufrufende Methode den Grund des Fehlers erkennen kann und dadurch entscheiden kann ob ein Commit oder ein Rollback durchgeführt werden soll.

if (retval == 0)
{
if (localTransaction )   // Nur wenn eine lokale Transaktion, dann ein Commit, wenn alles OK war.
{
tm.Commit();
}
}
else
{
if (localTransaction )   // Nur wenn eine lokale Transaktion, dann ein Rollback wenn ein Fehler auftritt
{
tm.Rollback();
}
}

return retval;

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.