2013-07-22 94 views
1

我在我的C#代碼中使用事務。在TransactionScope中,我幾乎記錄了所有內容,以確保所有內容都在測試中完成。但是如果在事務中發生什麼事情,並且它會去捕捉我的日誌類不寫任何東西。在本地主機上,我將TransactionScopeOption更改爲「Suppress」,因爲數據庫不在我的服務器中。當我在調試時一切正常,我可以寫入日誌文件。但是當我更改爲「必需」,如果它給出錯誤,它會像往常一樣取消所有內容,但它也不能寫入第一個日誌。 我該如何解決這個問題?在C#中的TransactionScope嘗試/捕獲#

我的代碼示例:

所有的
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.Complete()之後一切都可以,但它也不能寫入日誌。 – Kadir

+0

這聽起來像是日誌記錄的問題。什麼是「LogProcess」?我不熟悉它。它在你的應用程序的其他地方工作嗎 –

回答

3

首先,我覺得你的代碼示例的結構相當混亂。在使用TransactionScope時,通常不會在調用scope.Complete()或scope.Dispose()之後編寫語句。此外,using語句爲你配置了範圍,所以恕我直言,如果你能幫助它,你不應該調用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

我明白你的要求,如果你的客戶要求輸入大量的日誌語句,我只是好奇你爲什麼選擇按照你的方式來實現它:每當你需要時實例化一個新對象並不常見記錄一些東西(假設LogProcess構造器執行實際的寫操作)。 –