Ich schreibe einen Integrationstest, bei dem ich eine Reihe von Objekten in eine Datenbank einfüge und dann überprüfe, 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 von TransactionScope erfahren, das anscheinend genau für diesen Zweck verwendet werden kann ...
Ein Beispielcode, den ich gefunden habe, lautet 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, wenn ich die Zeile nicht einbeziehe txScope.Complete()
, werden die eingefügten Daten zurückgesetzt. Aber leider verstehe ich nicht, wie das möglich ist ... wie verfolgt das txScope
Objekt die deptAdapter
und empAdapter
Objekte und ihre Transaktionen in der Datenbank.
Ich habe das Gefühl, dass mir hier ein paar Informationen fehlen ... Kann ich meine BeginTransaction()
und RollbackTransaction(
) Anrufe wirklich ersetzen, indem ich meinen Code mit umhülle TransactionScope
?
Wenn nicht, wie funktioniert dann das TransactionScope
Zurücksetzen von Transaktionen?
Antworten:
Im Wesentlichen verfolgt TransactionScope nicht die Adapter, sondern die Datenbankverbindungen. Wenn Sie eine DB-Verbindung öffnen, prüfen die Verbindungen, ob eine Umgebungstransaktion (Transaktionsbereich) vorliegt, und melden Sie sich gegebenenfalls bei dieser an. Achtung Wenn mehrere Verbindungen zu demselben SQL Server bestehen, wird dies zu einer verteilten Transaktion eskalieren.
Was passiert, wenn Sie einen using-Block verwenden, stellen Sie sicher, dass dispose auch dann aufgerufen wird, wenn eine Ausnahme auftritt. Wenn also dispose vor txScope.Complete () aufgerufen wird, weist das TransactionScope die Verbindungen an, ihre Transaktionen (oder den DTC) zurückzusetzen.
quelle
Die
TransactionScope
Klasse arbeitet mit derTransaction
Klasse , die threadspezifisch ist.Wenn das
TransactionScope
erstellt wird, wird überprüft, ob es einTransaction
für den Thread gibt. Wenn eine existiert, verwendet sie diese, andernfalls erstellt sie eine neue und schiebt sie auf den Stapel.Wenn ein vorhandener verwendet wird, wird nur ein Zähler für Releases erhöht (da Sie ihn aufrufen müssen
Dispose
). Wenn bei der letzten Version dasTransaction
nicht festgelegt wurde, wird die gesamte Arbeit zurückgesetzt.Der Grund, warum Klassen auf magische Weise über Transaktionen Bescheid wissen, bleibt als Implementierungsdetail für diejenigen Klassen übrig, die mit diesem Modell arbeiten möchten.
Wenn Sie Ihre
deptAdapter
undemptAdapter
Instanzen erstellen , prüfen sie, ob der Thread eine aktuelle Transaktion enthält (die statischeCurrent
Eigenschaft derTransaction
Klasse). Wenn dies der Fall ist, registriert es sich bei derTransaction
, um an derTransaction
Festschreibungs- / Rollback-Sequenz teilzunehmen (die unterschiedliche Transaktionskoordinatoren wie Kernel, verteilt usw. steuert und möglicherweise an diese weiterleitet).quelle