Как TransactionScope откатывает транзакции?

Я пишу интеграционный тест, в котором я буду вставлять несколько объектов в базу данных, а затем проверять, извлекает ли мой метод эти объекты.

Я подключаюсь к базе данных через 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 работает для отката транзакций?


person mezoid    schedule 30.01.2009    source источник
comment
Я никогда не использовал NHibernate, но, возможно, вам поможет эта ссылка.   -  person    schedule 30.01.2009
comment
Если вы ищете лучший способ управления сеансами NHibernate для группирования операций в транзакции, возможно, вы захотите проверить мое сообщение в блоге по этой теме dotnetchris.wordpress.com/2009/01/27/   -  person Chris Marisic    schedule 30.01.2009


Ответы (2)


По сути, TransactionScope не отслеживает ваш адаптер, он только отслеживает соединения с базой данных. Когда вы открываете соединение с БД, соединения будут проверять, есть ли внешняя транзакция (область транзакции), и, если да, присоединиться к ней. Внимание! Если к одному и тому же серверу SQL установлено несколько подключений, это перерастет в распределенную транзакцию.

Что происходит, поскольку вы используете блок using, вы гарантируете, что dispose будет вызываться даже в случае возникновения исключения. Поэтому, если dispose вызывается перед txScope.Complete (), TransactionScope сообщит соединениям об откате своих транзакций (или DTC).

person JoshBerke    schedule 30.01.2009
comment
TransactionScope не отслеживает ничего, кроме текущей транзакции в потоке, и при необходимости модифицирует ее на основе модели (требуется, требуется новая и т. Д. И т. Д.). Транзакция просто уведомляет все, что к ней присоединяется, а не только соединения с базой данных. - person casperOne; 30.01.2009
comment
Думаю, это не совсем так. Я частично отследил исходный код TransactionScope, и я также увидел это msdn.microsoft.com/en-us/library/ms172152 (v = vs.90) .aspx, в котором говорится, что если транзакция не была создана, фиксация выполняется всякий раз, когда Commit вызывается владелец объекта CommittableTransaction. В этот момент диспетчер транзакций вызывает диспетчеров ресурсов и сообщает им о необходимости фиксации или отката в зависимости от того, был ли вызван метод Complete для объекта TransactionScope. Трассировка источника также указывает на это поведение. - person user44298; 04.01.2011
comment
Я нашел этот SO Q&A полезным: IEnlistmentNotification - person mungflesh; 09.12.2014
comment
Мне все еще непонятно. Кажется, что объекты с методами, вызываемыми в рамках транзакции, должны взаимодействовать с механизмом транзакции. Они должны искать уведомления о фиксации / откате от системы и иметь возможность откатиться, поскольку именно они выполняют откат, когда это необходимо (если было выполнено удаление файла, очевидно, мы не можем волшебным образом откатить его, если не какая-то мера предосторожности). Также кажется, что операции SQL-сервера кооперативны. Но есть ли в .Net какой-либо другой кооперативный объект? А как написать кооперативный класс? Документация? - person mins; 30.07.2020

TransactionScope class работает с _ 2_ class, который зависит от потока.

Когда TransactionScope создается, он проверяет, есть ли Transaction для потока; если он существует, он использует его, в противном случае он создает новый и помещает его в стек.

Если он использует существующий, он просто увеличивает счетчик для выпусков (поскольку вам нужно вызвать _ 5_ на нем). В последнем выпуске, если Transaction не был завершен, он откатывает всю работу.

Что касается того, почему классы, кажется, волшебным образом знают о транзакциях, это оставлено в качестве детали реализации для тех классов, которые хотят работать с этой моделью.

Когда вы создаете свои экземпляры deptAdapter и emptAdapter, они проверяют, есть ли в потоке текущая транзакция (статический _ 9_ свойство в Transaction классе). Если есть, то он регистрируется в Transaction, чтобы принять участие в последовательности фиксации / отката (которая Transaction управляет и может распространяться на различные координаторы транзакций, такие как ядро, распределенные и т. Д.).

person casperOne    schedule 30.01.2009
comment
Как это работает с SqlConnection (s), созданным в области видимости? Использует ли класс SqlConnection внутри класс Transaction, который, в свою очередь, подключается к TransactionScope? Или он напрямую подключается к TLS? - person Kakira; 08.08.2014