Estou escrevendo um teste de integração onde irei inserir vários objetos em um banco de dados e, em seguida, verificar se meu método recupera esses objetos.
Minha conexão com o banco de dados é através do NHibernate ... e meu método usual de criar tal teste seria fazer o seguinte:
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();
No entanto, descobri recentemente sobre o TransactionScope, que aparentemente pode ser usado para essa finalidade ...
Alguns exemplos de código que encontrei são os seguintes:
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;
}
Acredito que se não incluir a linha txScope.Complete()
que os dados inseridos serão revertidos. Mas, infelizmente, eu não entendo como isso é possível ... como é que o txScope
objeto manter uma faixa da deptAdapter
e empAdapter
objetos e suas transações no banco de dados.
Sinto que estou faltando um pouco de informação aqui ... sou realmente capaz de substituir minhas chamadas BeginTransaction()
e RollbackTransaction(
) cercando meu código usando TransactionScope
?
Se não, como TransactionScope
funciona para reverter as transações?
fonte
Respostas:
Essencialmente, o TransactionScope não rastreia o seu adaptador, o que ele faz é rastrear conexões de banco de dados. Quando você abre uma conexão de banco de dados, as conexões verificarão se há uma transação ambiente (Escopo da transação) e se houver, se alistarão nela. Cuidado, se houver mais de uma conexão com o mesmo servidor SQL, isso será escalado para uma Transação Distribuída.
O que acontece, já que você está usando um bloco de uso e está garantindo que dispose será chamado mesmo se ocorrer uma exceção. Portanto, se dispose for chamado antes de txScope.Complete (), o TransactionScope dirá às conexões para reverter suas transações (ou o DTC).
fonte
A
TransactionScope
classe trabalha com aTransaction
classe , que é específica do segmento.Quando o
TransactionScope
é criado, ele verifica se há umTransaction
para o segmento; se houver um, ele o usa; caso contrário, cria um novo e o coloca na pilha.Se ele usa um existente, ele apenas incrementa um contador para lançamentos (já que você tem que chamá
Dispose
-lo). No último lançamento, seTransaction
não for comprometido, ele reverte todo o trabalho.Quanto ao motivo pelo qual as classes parecem saber magicamente sobre as transações, isso é deixado como um detalhe de implementação para as classes que desejam trabalhar com este modelo.
Quando você cria suas instâncias
deptAdapter
eemptAdapter
, eles verificam se há uma transação atual no encadeamento (aCurrent
propriedade estática naTransaction
classe). Se houver, ele se registra com oTransaction
, para participar da sequência de confirmação / reversão (queTransaction
controla e pode se propagar para vários coordenadores de transação, como kernel, distribuído, etc.).fonte