it-swarm-eu.dev

Wie setzt TransactionScope Transaktionen zurück?

Ich schreibe einen Integrationstest, in dem ich eine Reihe von Objekten in eine Datenbank einfügen und dann überprüfen werde, ob meine Methode diese Objekte abruft.

Meine Verbindung zur Datenbank erfolgt über NHibernate ... und meine übliche Methode zum Erstellen eines solchen Tests besteht darin, Folgendes zu tun:

NHibernateSession.BeginTransaction();

//use nhibernate to insert objects into database
//retrieve objects via my method
//verify actual objects returned are the same as those inserted

NHibernateSession.RollbackTransaction();

Ich habe jedoch kürzlich herausgefunden, dass TransactionScope anscheinend für genau diesen Zweck verwendet werden kann ...

Einige Beispielcode habe ich gefunden ist wie folgt:

public static int AddDepartmentWithEmployees(Department dept)
{

    int res = 0;

    DepartmentAdapter deptAdapter = new DepartmentAdapter();
    EmployeeAdapter empAdapter = new EmployeeAdapter();
    using (TransactionScope txScope = new TransactionScope())
    {

        res += deptAdapter.Insert(dept.DepartmentName);
        //Custom method made to return Department ID 
        //after inserting the department "Identity Column"
        dept.DepartmentID = deptAdapter.GetInsertReturnValue();
        foreach(Employee emp in dept.Employees)
        {

            emp.EmployeeDeptID = dept.DepartmentID;
            res += empAdapter.Insert(emp.EmployeeName, emp.EmployeeDeptID);

        }
        txScope.Complete();

    }
    return res;

}

Ich glaube, dass die eingefügten Daten zurückgesetzt werden, wenn ich die Zeile txScope.Complete() nicht einbeziehe. Aber leider verstehe ich nicht, wie das möglich ist ... Wie verfolgt das Objekt txScope die Objekte deptAdapter und empAdapter und ihre Transaktionen in der Datenbank.

Ich habe das Gefühl, dass mir hier ein paar Informationen fehlen ... kann ich meine BeginTransaction() - und RollbackTransaction() - Aufrufe wirklich ersetzen, indem ich meinen Code mit TransactionScope umgehe?

Wenn nicht, wie funktioniert dann TransactionScope, um Transaktionen zurückzusetzen?

94
mezoid

Im Wesentlichen verfolgt TransactionScope nicht die Daten Ihres Adapters, sondern nur die Datenbankverbindungen. Wenn Sie eine DB-Verbindung öffnen, prüfen die Verbindungen, ob eine Ambient-Transaktion (Transaction Scope) vorhanden ist, und melden Sie sich bei dieser an. Vorsicht: Wenn mehr als eine Verbindung zum gleichen SQL Server besteht, wird dies zu einer Distribtued Transaction eskaliert.

Was passiert, wenn Sie einen using-Block verwenden und sicherstellen, dass dispose ausgeführt wird, wird auch dann aufgerufen, wenn eine Ausnahme auftritt. Wenn also dispose vor txScope.Complete () aufgerufen wird, weist TransactionScope die Verbindungen an, ihre Transaktionen (oder den DTC) zurückzusetzen.

104
JoshBerke

Die TransactionScope Klasse arbeitet mit der Transaction Klasse , die threadspezifisch ist.

Beim Erstellen von TransactionScope wird geprüft, ob für den Thread ein Transaction vorhanden ist. Wenn einer existiert, verwendet er diesen, andernfalls erstellt er einen neuen und legt ihn auf den Stapel.

Wenn es ein vorhandenes verwendet, erhöht es nur einen Zähler für Releases (da Sie Dispose aufrufen müssen). In der letzten Version wird die gesamte Arbeit zurückgesetzt, wenn Transaction nicht festgeschrieben wurde.

Da Klassen scheinbar auf magische Weise etwas über Transaktionen wissen, verbleibt dies als Implementierungsdetail für die Klassen, die mit diesem Modell arbeiten möchten.

Wenn Sie Ihre Instanzen deptAdapter und emptAdapter erstellen, prüfen sie, ob im Thread eine aktuelle Transaktion vorhanden ist (die Eigenschaft static Current on die Klasse Transaction). Wenn dies der Fall ist, registriert es sich bei Transaction, um an der Festschreibungs-/Rollback-Sequenz teilzunehmen (die Transaction steuert und möglicherweise an verschiedene Transaktionskoordinatoren wie den verteilten Kernel weiterleitet). etc.).

52
casperOne