2010-02-17 133 views
23

很多例子了數據庫事務的主張有明確的回退,沿着線:顯式事務回滾是否必需?

using (var transaction = ...) 
{ 
    try 
    { 
     // do some reading and/or writing here 

     transaction.Commit(); 
    } 
    catch (SqlException ex) 
    { 
     // explicit rollback 
     transaction.Rollback(); 
    } 
} 

不過,我傾向於這樣做:

using (var transaction = ...) 
{ 
    // do some reading and/or writing here 

    transaction.Commit(); 
} 

當異常發生時,我只是憑着隱式回滾未提交的事務。

依賴這種隱式行爲是否存在問題?有沒有人有一個令人信服的理由,爲什麼我不應該這樣做?

+1

您的問題中的示例代碼可以說是有缺陷的,因爲它不會重新拋出。也許忘記這種傾向是避免這種模式的理由? :) – 2010-02-17 15:30:24

+0

誰說你想重新拋出?在很多情況下,回滾事務可以被視爲處理異常。 – 2010-02-17 16:08:47

+1

你提出了兩個不同的「選項」。對於第一個行爲像第二個,它必須重新拋出。爲了相當,兩個例子中的一個需要改變。 – 2010-02-17 17:54:40

回答

13

不,它不是特別需要,但是我能想到的兩個原因爲什麼它可能是一個好主意:

  • 清晰

有些人可能會認爲,使用transaction.Rollback()使得下更清楚什麼情況下交易將不會被提交。當事務回滾或提交

  • 釋放鎖

當與交易處理重要的是要實現一定的鎖纔會被釋放。如果您使用的是using語句,那麼事務將在事務處理完成時回退,但如果由於某種原因您需要在using塊中執行一些錯誤處理,則回滾事務(移除鎖定)在執行復雜/耗時的錯誤處理之前。

1

我想可以回答第一種方法對維護你的代碼的人更具可讀性。編碼的明確性使目標清晰而迅速。雖然隱含的回滾對你來說很清楚,並且可能任何人對交易處理的掌握不止一個知識,但對其他人可能不是。這就是說,有幾條評論很快就會糾正這一點。唯一的問題是如果隱式回滾不是該對象的文檔化特徵。

所以,我想說,如果您提供了對操作的評論,並且您可以依賴隱式操作,那麼沒有充分的理由去採用顯式方法。

1

正確編寫的ADO.NET連接將回滾未明確提交的事務。所以這不是必須的。

我看到一個明確的Rollback()的主要好處是它能夠在那裏設置斷點,然後檢查連接或數據庫以查看發生了什麼。未來的代碼維護者對於不同執行路徑下發生的事情也更加清楚。

0

只要交易在using()塊中完全獨立,那麼您就很好。但是,如果某人(如果您從調用方傳遞了現有的事務對象)問題可能會出現,並且確實會出現問題。但這是一個不同的場景......

3

我看到兩個問題您的使用情況:

  1. 你依靠交易的Dispose()方法來回滾未提交的事務,建立一個第三方的實現了IDisposable的依賴。在這種情況下,風險是微不足道的,但不是一個好的做法。
  2. 您錯過了記錄和/或處理異常的機會。此外,我會趕上異常而不是SqlException。
+0

異常管理和日誌記錄進一步發生在我的堆棧中。第一個樣本不是我的 - 這就是您通常會找到的示例交易管理代碼。 – 2010-02-17 14:59:39

+0

IMO,日誌應該總是儘可能接近例外。使用事務總是有可能發生異常,所以應該總是有try..catch塊。 – 2010-02-17 15:21:07

+2

那麼,這是你的意見,你有權:) – 2010-02-17 16:07:24