Estoy escribiendo una prueba de integración en la que insertaré varios 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 una prueba de este tipo 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 se puede usar para este mismo propósito ...
Un código de ejemplo que encontré es el siguiente:
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 incluyo la línea, txScope.Complete()los datos insertados se revertirán. Pero, por desgracia no entiendo cómo es posible ... ¿cómo el txScopeobjeto mantener un seguimiento de la deptAdaptery empAdapterlos objetos y sus transacciones en la base de datos.
Siento que me falta un poco de información aquí ... ¿realmente puedo reemplazar mis llamadas BeginTransaction()y RollbackTransaction() rodeando mi código usando TransactionScope?
Si no es así, ¿cómo funciona entonces TransactionScoperevertir las transacciones?
fuente

Respuestas:
Básicamente, TransactionScope no rastrea su Adaptador, lo que hace es rastrear las conexiones de la base de datos. Cuando abre una conexión de base de datos, las conexiones verán si hay una transacción ambiental (alcance de transacción) y, si es así, se alistará en ella. Precaución si hay más de una conexión al mismo servidor SQL, esto escalará a una transacción distribuida.
¿Qué sucede ya que está usando un bloque de uso? Se asegura de que se llamará a dispose incluso si ocurre 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).
fuente
La
TransactionScopeclase trabaja con laTransactionclase , que es específica del hilo.Cuando
TransactionScopese crea, comprueba si hay unTransactionpara el hilo; si existe, lo usa; de lo contrario, crea uno nuevo y lo coloca en la pila.Si usa uno existente, simplemente incrementa un contador para lanzamientos (ya que tiene que llamarlo
Dispose). En el último lanzamiento, siTransactionno se comprometió, revierte todo el trabajo.En cuanto a por qué las clases parecen saber mágicamente sobre transacciones, eso se deja como un detalle de implementación para aquellas clases que deseen trabajar con este modelo.
Cuando crea sus instancias
deptAdapteryemptAdapter, comprueban si hay una transacción actual en el hilo (laCurrentpropiedad estática de laTransactionclase). Si lo hay, entonces se registra a sí mismo con elTransaction, para participar en la secuencia de confirmación / retroceso (queTransactioncontrola y podría propagarse a diferentes coordinadores de transacciones, como kernel, distribuidos, etc.).fuente