¿Cómo retracta TransactionScope las transacciones?

Estoy escribiendo una prueba de integración en la que insertaré una cantidad de objetos en una base de datos y luego verificaré si mi método recupera esos objetos.

Mi conexión a la base de datos es a través de NHibernate … y mi método habitual para crear dicha prueba sería hacer lo siguiente:

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(); 

Sin embargo, recientemente descubrí TransactionScope que aparentemente puede usarse para este propósito …

Algunos ejemplos de código que he encontrado son los siguientes:

 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; } 

Creo que si no txScope.Complete() la línea txScope.Complete() los datos insertados se revertirán. Pero desafortunadamente no entiendo cómo es posible … ¿cómo hace el objeto txScope mantener un seguimiento de los objetos deptAdapter y empAdapter y sus transacciones en la base de datos.

Siento que me falta algo de información aquí … ¿realmente puedo reemplazar mis BeginTransaction() y RollbackTransaction( ) rodeando mi código usando TransactionScope ?

Si no, ¿cómo funciona TransactionScope para deshacer transacciones?

Básicamente, TransactionScope no rastrea su Adaptador, lo que hace es que rastrea las conexiones de la base de datos. Cuando abre una conexión de BD, las conexiones se verán si hay una transacción ambiental (Alcance de la transacción) y, si es así, se alistó con ella. Precaución si hay más de una conexión con el mismo servidor SQL esto escalará a una transacción distribuida.

Lo que sucede ya que está usando un bloque de uso que está garantizando, se llamará incluso si se produce una excepción. Entonces, si se llama a dispose antes de txScope.Complete (), TransactionScope le dirá a las conexiones que deshagan sus transacciones (o el DTC).

La clase TransactionScope funciona con la clase Transaction , que es específica de subprocesos.

Cuando se crea el TransactionScope , comprueba si hay una Transaction para el hilo; si uno existe, entonces usa eso; de lo contrario, crea uno nuevo y lo empuja a la stack.

Si usa uno existente, entonces simplemente incrementa un contador para las versiones (ya que tiene que llamar a Dispose en él). En el último lanzamiento, si la Transaction no se realizó, revierte todo el trabajo.

En cuanto a por qué las clases parecen saber mágicamente sobre las transacciones, eso se deja como un detalle de implementación para aquellas clases que desean trabajar con este modelo.

Cuando crea sus instancias deptAdapter y emptAdapter , verifican si hay una transacción actual en el hilo (la propiedad de Current estática en la clase Transaction ). Si lo hay, se registra con la Transaction , para participar en la secuencia de confirmación / restitución (que controla la Transaction , y puede propagarse a diferentes coordinadores de transacción, como kernel, distribuido, etc.).