Я пишу интеграционный тест, в котором я буду вставлять несколько объектов в базу данных, а затем проверять, получает ли мой метод эти объекты.
Мое подключение к базе данных осуществляется через NHibernate ... и мой обычный метод создания такого теста заключался бы в следующем:
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();
Однако недавно я узнал о TransactionScope, который, по-видимому, можно использовать именно для этой цели ...
Некоторые из примеров кода я нашел это следующим образом :
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;
}
Я считаю, что если я не добавлю строку txScope.Complete()
, то вставленные данные будут откатаны. Но , к сожалению , я не понимаю , как это возможно ... как же txScope
объект сохранить трек deptAdapter
и empAdapter
объектов и их операции по базе данных.
Я чувствую, что мне здесь не хватает информации ... действительно ли я могу заменить свои вызовы BeginTransaction()
и RollbackTransaction(
) окружением моего кода с помощью TransactionScope
?
Если нет, то как тогда TransactionScope
откат транзакций?
Ответы:
По сути, TransactionScope не отслеживает ваш адаптер, он только отслеживает соединения с базой данных. Когда вы открываете соединение с БД, соединения будут проверять, есть ли внешняя транзакция (область транзакции), и, если да, присоединиться к ней. Внимание! Если существует несколько подключений к одному серверу SQL, это перерастет в распределенную транзакцию.
Что происходит, поскольку вы используете блок using, вы гарантируете, что dispose будет вызываться даже в случае возникновения исключения. Таким образом, если dispose вызывается перед txScope.Complete (), TransactionScope сообщит соединениям об откате своих транзакций (или DTC).
источник
TransactionScope
Класс работает сTransaction
классом , который является поточно-специфичны.Когда
TransactionScope
создается, он проверяет, есть лиTransaction
для потока; если он существует, он использует его, в противном случае он создает новый и помещает его в стек.Если он использует существующий, он просто увеличивает счетчик для выпусков (поскольку вы должны его вызвать
Dispose
). В последнем выпуске, еслиTransaction
он не был завершен, откатывает всю работу.Что касается того, почему классы, похоже, волшебным образом знают о транзакциях, это оставлено в качестве детали реализации для тех классов, которые хотят работать с этой моделью.
При создании
deptAdapter
иemptAdapter
экземпляров, они проверяют , чтобы видеть, есть ли текущая транзакция на резьбе (статическиеCurrent
собственности наTransaction
классе). Если есть, то он регистрируется вTransaction
, чтобы принять участие в последовательности фиксации / отката (котораяTransaction
контролирует и может распространяться на различные координаторы транзакций, такие как ядро, распределенные и т. Д.).источник