Вложенные транзакции в LINQ to SQL - PullRequest
3 голосов
/ 21 октября 2008

Мне нужна помощь в реализации довольно сложной бизнес-логики, которая работает со многими таблицами и выполняет довольно много команд 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, а если нет - как бы вы подошли к такой проблеме?

1 Ответ

2 голосов
/ 22 октября 2008

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

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

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...