2013-07-22 2 views
1

Я использую транзакцию в моем коде C#. В TransactionScope я регистрирую почти все, чтобы убедиться, что все сделано в тестировании. Но если что-то происходит в транзакции, и оно идет, чтобы поймать мой класс журнала, ничего не пишет. В localhost я меняю TransactionScopeOption на «Подавить», потому что базы данных не на моем сервере. Когда я отлаживаю все в порядке, я могу записать в файл журнала. Но когда я перехожу на «Обязательный», если он дал ошибку, он отменил все как обычно, но также не может записать первый журнал. Как я могу это исправить?try/catch в TransactionScope в C#

Мой пример кода:

TransactionOptions tr = new TransactionOptions(); 
tr.IsolationLevel = System.Transactions.IsolationLevel.Serializable; 
using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required, tr, System.Transactions.EnterpriseServicesInteropOption.Automatic))//System.TimeSpan.MaxValue)) 
{ 
    bool status = false; 
    // this log must be written anyway but it won't when it gives an error. 
    LogProcess log = new LogProcess(Ssession["DBNAME"], new Guid(), "Transaction begun."); 
    try 
    { 
     // process 1 
     // process 2 
     . 
     . 
     . 
     if(status) 
     { 
      LogProcess log1 = new LogProcess(Ssession["DBNAME"], new Guid(), "Transaction will complete soon."); 
      scope.Complete(); 
      LogProcess log1 = new LogProcess(Ssession["DBNAME"], new Guid(), "Transaction completed."); 
     } 
     else 
     { 
      LogProcess log2 = new LogProcess(Ssession["DBNAME"], new Guid(), "Transaction will dispose."); 
      scope.Dispose(); 
      LogProcess log2 = new LogProcess(Ssession["DBNAME"], new Guid(), "Transaction disposed."); 
     } 

    } 
    catch(Exception ex) 
    { 
     LogProcess log1 = new LogProcess(Ssession["DBNAME"], new Guid(), "Transaction exception. Error: " + ex.Message); 
     scope.Dispose(); 
    } 
} 
+2

Является ли журнал записанным в базе данных? Если да, то это твоя проблема. При возникновении ошибки журнал также откатывается. Вам необходимо обернуть журнал в другую транзакцию или войти в другое место, как текстовый файл. – tucaz

+0

@tucaz Спасибо, ты прав. Но даже после завершения scope все нормально. Завершить() он также не может записывать в журнал. – Kadir

+0

Это звучит как проблема с протоколированием. Что такое «LogProcess»? Я не знаком с ним. Работает ли он в другом месте вашего приложения? –

ответ

3

Прежде всего, я считаю, что структуры вашего образца кода довольно запутанным. При использовании TransactionScope вы, как правило, не записываете заявления после scope.Complete() или scope.Dispose() были вызваны. Более того, оператор using предоставляет вам область действия, поэтому IMHO вы не должны вызывать scope.Dispose() явно, если вы можете помочь. Другими словами: попробуйте реорганизовать код так, что он выглядит примерно так:

private void PerformTransactionalOperation() 
{ 
    Log.Write("Starting operation.");   

    try 
    { 
     using (var scope = CreateTransactionScope()) 
     { 
      if (PerformTransactionalOperationCore()) 
      { 
       Log.Write("Committing..."); 
       scope.Complete(); 
       Log.Write("Committed"); 
      } 
      else 
      { 
       Log.Write("Operation aborted."); 
      } 
     } 
    } 
    catch (Exception exception) 
    { 
     Log.Write("Operation failed: " + exception.Message); 
     throw; 
    } 
} 

private bool PerformTransactionalOperationCore() 
{ 
    // Perform operations and return status... 
} 

Во-вторых, сделка-сфера была специально разработана для выполнения только тогда, когда исключение не поднимался, так что ваш дизайн может быть улучшен, позволяя PerformTransactionalOperationCore выдает конкретное исключение вместо возврата false.

Затем на вопрос о регистрации: убедитесь, что ваша система ведения журнала не участвует в той же транзакции, что и операция, о которой вы регистрируетесь. Вы можете сделать это, всегда регистрируясь в TransactionScope с опцией Подавите (то есть, когда вы регистрируетесь на ресурсе, который в первую очередь связан с транзакциями, например в базе данных). И, кстати, почему вы записываете логические операторы, создавая экземпляры экземпляров LogProcess?

+0

Я попробую. Спасибо. Мой класс журнала обычно очень широк. Мой клиент хочет увидеть почти все. Это было всего лишь примером для тестирования. – Kadir

+1

Насколько я понимаю, ваше требование вложить много логических операторов, если ваш клиент этого требует, мне было просто любопытно, почему вы решили реализовать его так, как вы это делали: не так просто создавать экземпляр нового объекта каждый раз, когда вам нужно log something (при условии, что LogProcess-contructor выполняет фактическую запись). –

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