Вложенные транзакции в LINQ to SQL

Мне нужна помощь в реализации довольно сложной бизнес-логики, которая работает со многими таблицами и выполняет довольно много команд SQL. Однако я хочу быть уверен, что данные не останутся в несостоятельном состоянии, и на данный момент я не вижу решения, которое не требовало бы вложенных транзакций. Я написал простой псевдокод, который иллюстрирует сценарий, аналогичный тому, что я хочу выполнить:

Dictionary<int, bool> opSucceeded = new Dictionary<int, bool> ();

for (int i = 0; i < 10; i++)
{
    try
    {   
        // this operation must be atomic
        Operation(dbContext, i);

        // commit (?)

        opSucceeded[i] = true;
    }
    catch
    {
        // ignore
    }
}

try
{
    // this operation must know which Operation(i) has succeeded;
    // it also must be atomic
    FinalOperation(dbContext, opSucceeded);

    // commit all
}
catch
{
    // rollback FinalOperation and operation(i) where opSucceeded[i] == true
}

Самая большая проблема для меня: как гарантировать, что в случае сбоя FinalOperation все успешные операции Operation (i) будут отменены? Обратите внимание, что я также хотел бы иметь возможность игнорировать сбои одной операции (i).

Можно ли добиться этого с помощью вложенных объектов TransactionScope, а если нет - как бы вы подойти к такой проблеме?


person user29930    schedule 21.10.2008    source источник


Ответы (1)


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

Оттуда у вас есть последняя операция, которая должна откатить все предыдущие успешные операции, если она не удалась сама.

Казалось бы, это именно тот случай, для которого предназначена простая транзакция. Нет необходимости отслеживать успех или неудачу дочерних / ранних операций до тех пор, пока сбой последней операции откатывает всю транзакцию назад (здесь предполагается, что FinalOperation не использует эту информацию по другим причинам).

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

Может, я чего-то упускаю? (Обратите внимание: если вы хотите СОХРАНИТЬ более ранние / дочерние операции, это будет совсем другое дело ... но отказ последней операции отката всего пакета операций назад делает простую транзакцию пригодной для использования).

person Godeke    schedule 21.10.2008