TransactionScope проти транзакції в LINQ to SQL


76

Які відмінності між класичним шаблоном транзакцій у LINQ to SQL:

using(var context = Domain.Instance.GetContext())
{
    try
    {
        context.Connection.Open();
        context.Transaction = context.Connection.BeginTransaction();
        /*code*/
        context.Transaction.Commit();
    }
    catch
    {
        context.Transaction.Rollback();
    }         
}

проти об’єкта TransactionScope

using (var context = Domain.Instance.GetContext())
using (var scope = new TransactionScope())
{
    try
    {
        /*code*/
        scope.Complete();
    }
    catch
    {
    }
}

Відповіді:


37

Linq2SQL використовуватиме неявну транзакцію. Якщо всі ваші оновлення виконуються в межах однієї Подання, можливо, вам не доведеться самостійно обробляти транзакцію.

З документації (курсив мій):

Коли ви викликаєте SubmitChanges, LINQ to SQL перевіряє, чи знаходиться виклик у межах транзакції, чи властивість транзакції (IDbTransaction) встановлено на локальну транзакцію, яку запускає користувач. Якщо він не знаходить жодної транзакції, LINQ to SQL запускає локальну транзакцію (IDbTransaction) і використовує її для виконання згенерованих команд SQL. Коли всі команди SQL успішно виконані, LINQ to SQL здійснює локальну транзакцію та повертається.


10
Якщо вам потрібно надіслати щось із циклічними властивостями (загальне), ви потрапляєте в LINQ to SQL про помилку, яка вимагає видалення однієї частини кожного двостороннього посилання, подання, відновлення двостороннього посилання та повторного надсилання. Для цього потрібно обернути все це власною транзакцією. Це загальноприйнята потреба, тому «не турбуйся про це» - не найкраща відповідь.
Chris Moschini,

76

Слід зазначити, що при використанні TransactionScopeнемає необхідності у try/catchвашій конструкції. Вам просто потрібно зателефонувати Completeдо області, щоб здійснити транзакцію, коли область дії виходить.

Сказане, TransactionScopeяк правило, є кращим вибором, оскільки це дозволяє вкладати виклики до інших методів, які можуть вимагати транзакції, без необхідності передавати стан транзакції навколо.

При дзвінку BeginTransactionна DbConnectionоб'єкт, ви повинні передати цей об'єкт транзакції навколо , якщо ви хочете , щоб виконувати інші операції в одній і тій же операції, але в іншому методі.

До TransactionScopeтих пір, поки існує область дії, вона буде обробляти все, що реєструється з потоком Transactionу потоці, роблячи ваш код чистішим та ремонтопридатнішим.

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

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

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

Або , якщо ви знаєте, що будете використовувати один ресурс послідовно (і в тому самому потоці), можливо, ви захочете створити клас, який посилає-підраховує ваше з’єднання / транзакцію.

Ви створили б клас, який при побудові створює ваш ресурс / збільшує кількість. Він також реалізує IDisposable(в якому ви зменшуєте / звільняєте / фіксуєте / перериваєте, коли відлік дорівнює нулю), і зберігає рахунок у змінній, яка ThreadStaticAttributeдо нього застосована.

Це дозволяє відокремити управління транзакціями від логічного коду і при цьому досить ефективно утримувати окремий ресурс (замість того, щоб перерости до розподіленої транзакції).


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

@Parhs Залежить від того, чи є у вас інші транзакційні ресурси, залучені до транзакції з одним підключенням до бази даних.
casperOne

мій постачальник не дозволяє вкладені транзакції (база даних), тож проблема все ще є?
GorillaApe

2
@Parhs Це не про постачальника баз даних, але у вас може бути транзакційна файлова система, транзакційна веб-служба тощо. Якщо ці речі включені в транзакцію з одним підключенням до бази даних, DTC
вводить

21

Одна велика різниця (урок, засвоєний важким способом) - TransactionScope використовує MS DTC для управління транзакціями.

Якщо ваша програма повинна керувати лише транзакціями баз даних, а послуги та віддалені дзвінки не задіяні, ви можете пропустити потенційні проблеми, пов’язані з MS DTC, використовуючи транзакції, власні для баз даних (DbTransaction).


Я також тільки що дізнався це важкий шлях! Але радий, що вирішив кошмар із msdtc
DevDave

Mayank (або хтось інший). Я зіткнувся з подальшими проблемами з Transaction та UnitTesting, чи не могли б Ви мені допомогти з цим stackoverflow.com/questions/9636533/… ?
DevDave

6
Це не завжди відповідає дійсності. TransactionScopeпереросте від транзакції ядра до транзакції DTC, залежно від потреби. Однак це все приховано від вас. Важливим моментом є те, що це робиться не завжди , а за потреби .
casperOne

Ні, якщо ви використовуєте той самий контекст даних.
Дасід Віджес,

7

TransactionScope забезпечує уніфіковане управління всіма менеджерами ресурсів (SQL-сервер, активний каталог, файлова система…). Більше того, можна написати власний менеджер ресурсів: код, який виявляє обсяг транзакції, приєднується до неї і працює точно так, як це робить SQL-сервер: фіксує або повертає зміни, як інші учасники транзакції. Я вважав, що TransactionScope є загальноприйнятим, і забув власні транзакції MS SQL, поки не провалився у величезну пастку: Windows Server 2008 WEB Edition поставляється з обмеженою службою розподілених координаторів транзакцій, а область транзакцій працює лише на одному комп'ютері. Ваша програма ASP.NET вийде з ладу в цій системі, якщо IIS та SQL-сервер встановлені на різних комп'ютерах. Візьміть до уваги, що більшість постачальників послуг публічного домену постачають веб-версію Windows Server та SQL-сервер на окремих серверах. Це означає, що ви повинні працювати з власними транзакціями, використовуючи явне управління транзакціями ...


4

Я вважаю, що вони принципово однакові, що клас TransactionScope буде взаємодіяти з базовим підключенням ADO.NET, щоб створити транзакцію або зробити її фіксацією або відкатом. Те, що клас TransactionScope був щойно створений для того, щоб зробити роботу з засобом очищення стійкості ADO.NET.

Редагувати: Уточнюючи мою заяву щодо додавання casperOne, саме TransactionScope створить транзакцію, а з'єднання побачить транзакцію, створену TransactionScope, і використає її, оскільки вона для неї доступна.


@Christ Marisic: Це навпаки. З’єднання шукає наявність транзакції для поточного потоку, який буде створений TransactionScope. Якщо він є, то він реєструється з транзакцією. Потім координатор скаже підключенню, щоб здійснити фіксацію або відкат.
casperOne
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.