2008-10-21 5 views
3

Мне нужна помощь в реализации довольно сложной бизнес-логики, которая работает на многих таблицах и выполняет довольно много SQL-команд. Однако я хочу быть уверенным, что данные не останутся в неустойчивом состоянии, и к этому моменту я не вижу решения, которые не требуют вложенных транзакций. Я написал простой псевдо-код, который иллюстрирует сценарий, аналогичный тому, что я хочу сделать:Вложенные транзакции в LINQ to 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 не удается, все операции Операция (я), которые удалось откатываются назад? Обратите внимание, что я также хотел бы игнорировать сбои в одной операции (i).

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

ответ

2

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

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

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

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

Возможно, я что-то не хватает? (Обратите внимание, что если вы хотите RETAIN предыдущие/дочерние операции, это было бы совершенно иначе ... но сбой окончательной операции, выполняющей весь пакет операций назад, упрощает транзакцию).

Смежные вопросы