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 txScope
objeto mantener un seguimiento de la deptAdapter
y empAdapter
los 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 TransactionScope
revertir 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
TransactionScope
clase trabaja con laTransaction
clase , que es específica del hilo.Cuando
TransactionScope
se crea, comprueba si hay unTransaction
para 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, siTransaction
no 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
deptAdapter
yemptAdapter
, comprueban si hay una transacción actual en el hilo (laCurrent
propiedad estática de laTransaction
clase). Si lo hay, entonces se registra a sí mismo con elTransaction
, para participar en la secuencia de confirmación / retroceso (queTransaction
controla y podría propagarse a diferentes coordinadores de transacciones, como kernel, distribuidos, etc.).fuente