Подтвердить что ты не робот

Откат вложенной/дочерней транзакции

Я пытаюсь вложить TransactionScopes (.net 4.0), поскольку вы бы вложили транзакции в SQL Server, но похоже, что они работают по-разному. Я хочу, чтобы мои дочерние транзакции могли откатываться, если они терпят неудачу, но позволяют родительской транзакции решить, следует ли совершать/откатывать всю операцию. Проблема заключается в том, когда происходит первое заполнение, транзакция откатывается. Я понимаю, что завершение отличается от фиксации.

Очень упрощенный пример того, что я пытаюсь сделать:

static void Main(string[] args)
{
    using(var scope = new TransactionScope()) // Trn A
    {
        // Insert Data A

        DoWork(true);
        DoWork(false);

        // Rollback or Commit
    }
}

// This class is a few layers down
static void DoWork(bool fail)
{
    using(var scope = new TransactionScope()) // Trn B
    {
        // Update Data A

        if(!fail)
        {
            scope.Complete();
        }
    }
}

Я не могу использовать опции Suppress или RequiresNew, поскольку Trn B полагается на данные, вставленные Trn A. Если я использую эти параметры, Trn B блокируется Trn A.

Любые идеи о том, как я могу заставить его работать, или если это возможно даже с использованием пространства имен System.Transactions?

Спасибо

4b9b3361

Ответ 1

Вам, вероятно, не понравится этот ответ, но...

Голосование внутри вложенной области

Хотя вложенная область может присоединиться к внешней транзакции корневой области, вызов Полный во вложенной области не влияет на область корня. Только если все области действия от корневой области до последней вложенной области голосуют для фиксации транзакции, транзакция будет выполнена.

(Из Внедрение неявной транзакции с использованием области транзакций)

К сожалению, класс TransactionScope не предоставляет никакого механизма (который я знаю) для разделения единиц работы. Это все или ничего. Вы можете предотвратить любую транзакцию на определенной единице работы с помощью TransactionScopeOption.Suppress, но это, вероятно, не то, что вы хотите, так как тогда вы потеряете атомарность для того, что находится внутри этой области.

При использовании TransactionScope существует только одна "окружающая" транзакция. Когда a TransactionScope удаляется или собирается без выполнения Complete, вся окружающая транзакция возвращается обратно; что он, игра закончилась.

Фактически SQL Server вообще не поддерживает истинные вложенные транзакции, хотя возможно (хотя и несколько неинтуитивно) достичь того же конечного результата с соответствующим использованием операторов SAVE TRAN. Повторная реализация этой логики как хранимой процедуры (или нескольких из них) может быть вашим лучшим вариантом, если вам требуется это конкретное поведение.