Як TransactionScope повертає транзакції?


99

Я пишу тест на інтеграцію, де я буду вставляти в базу даних деякі об'єкти, а потім перевіряю, чи мій метод отримує ці об’єкти.

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


Я ніколи не використовував NHibernate, але, можливо, це посилання вам допоможе.

Якщо ви шукаєте кращий спосіб керувати своїми сесіями NHibernate для групових операцій з трансакціями, ви можете ознайомитися з моєю публікацією в цій темі. dotnetchris.wordpress.com/2009/01/27/…
Кріс Марісіч

Відповіді:


107

По суті TransactionScope не відслідковує адаптер, але він відстежує підключення до бази даних. Коли ви відкриєте з'єднання з БД, з'єднання виглядатимуть, якщо є зовнішня транзакція (Обсяг транзакцій), і якщо так, зарахуйте до неї. Обережно, якщо більше одного з'єднання з тим самим сервером SQL, це перейде до розподіленої транзакції.

Що відбувається з моменту використання блоку використання, який ви гарантуєте, що розпоряджатись, буде викликано навіть у випадку винятку. Тож якщо виклик розпоряджається перед txScope.Complete (), TransactionScope повідомить з'єднанням про відкат своїх транзакцій (або DTC).


10
TransactionScope не відстежує нічого, окрім поточної транзакції на потоці, та змінює її, якщо це потрібно, спираючись на модель (вимагає, вимагає нового тощо тощо). Угода просто сповіщає про все, що пов’язано з нею, а не лише підключення до бази даних.
casperOne

1
Я думаю, це не зовсім так. Я частково простежив вихідний код TransactionScope, і я також побачив це msdn.microsoft.com/en-us/library/ms172152(v=vs.90).aspx, який говорить: "Якби не створив транзакцію, фіксація відбувається, коли власник об'єкта ActivtableTransaction викликає комісію. У цей момент менеджер транзакцій викликає менеджерів ресурсів та повідомляє їх або здійснити, або відкатати, виходячи з того, чи був викликаний метод Complete на об'єкт TransactionScope. " Джерельний слід також вказує на цю поведінку.
user44298

Я вважаю це ТАК питанням
mungflesh

Досі мені незрозуміло. Здається, об'єкти з методами, викликаними в межах транзакції, повинні співпрацювати з механізмом транзакцій. Вони повинні шукати сповіщення про віддачу / відмову системою та мати можливість самостійно відмовлятись, оскільки саме вони виконують відкат, коли потрібно (якщо видалення файлу було виконано, очевидно, ми не можемо магічно повернути його назад, якщо не взяли якийсь запобіжний захід). Також здається, що операції SQL-сервера є спільними. Але чи є ще якийсь кооперативний об’єкт у .Net? І як написати клас, кооперативний? Документація?
хвилини

54

TransactionScopeКлас працює з Transactionкласом , який є поточно-специфічні.

Коли TransactionScopeфайл створено, він перевіряє, чи немає Transactionдля потоку; якщо хтось існує, він використовує те, інакше він створює новий і натискає на стек.

Якщо він використовує існуючий, він просто збільшує лічильник випусків (оскільки вам потрібно зателефонувати Disposeна нього). Після останнього випуску, якщо Transactionне було дозволено, він відкидає всю роботу.

Що стосується того, чому класи, здається, магічно знають про транзакції, то це залишається як деталь реалізації для тих класів, які хочуть працювати з цією моделлю.

При створенні deptAdapterі emptAdapterпримірників, вони перевіряють , щоб бачити, чи є поточна транзакція на різьбі (статичні Currentвласності на Transactionкласі). Якщо є, то він реєструється з допомогою Transaction, щоб взяти участь у послідовності фіксація / відкат (яка Transactionконтролює і може пропонувати різним координаторам транзакцій, таким як ядро, розподілений тощо).


4
Як це працює з SqlConnection (ими), створеними в межах області? Чи використовує клас SqlConnection внутрішньо клас Transaction, який в свою чергу зараховується до TransactionScope? Або це безпосередньо зараховано до TLS?
Какіра
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.