2010-11-19 18 views
0

您如何在代碼中使用事務?在C中處理事務的常用方式#

舊的好辦法是做這樣的事情:

try 
{ 
    IDbTransaction tx = Connection.BeginTransaction(); 
    perform_work1 
    perform_work2 
    perform_work3 
    tx.Commit(); 

} 
catch(DbException) 
{ 
    tx.Rollback(); 
    throw; 
} 

但後來你意識到你要DbExceptin記錄添加到您的軟件,並且應該更換的交易相關的代碼什麼樣子。

第一個想法是讓somethig與此類似:

public static class SafeCallerProxy 
    { 
     public delegate T ResultativeAction<T>(); 

     public static T ExecuteWithResult<T>(IDbConnection conn, ResultativeAction<T> action) 
     { 
      using(IDbTransaction tx = conn.BeginTransaction()) 
      { 
       try 
       { 
        T result = action(); 
        tx.Commit(); 
        return result; 
       } 
       catch (System.Data.DataException) 
       { 
        tx.Rollback(); 
        throw; 
       } 
      } 
     } 

     public static void ExecuteAction(IDbConnection conn, Action action) 
     { 
      using (IDbTransaction tx = conn.BeginTransaction()) 
      { 
       try 
       { 
        action(); 
        tx.Commit(); 
       } 
       catch (System.Data.DataException) 
       { 
        tx.Rollback(); 
        throw; 
       } 
      } 
     } 
    } 

使用

SafeCallerProxy.ExecuteAction(connection,() => 
{ 
    DoWork1(); 
    DoWork2(); 
    DoWork3(); 
} 
); 

而且我覺得我在這裏重塑bycicle。 請給出一個包含交易機制的好代碼的例子,

Sory爲我的英文。

+0

這實際上與我過去解決這個問題的方式非常相似。 – 2010-11-19 18:35:06

+0

爲什麼不在回滾事務時記錄DataException? – msarchet 2010-11-19 18:36:12

+1

僅供參考,在.NET 3.0中已經有一個'Func '委託,它的定義與您的'ResultativeAction '代表具有相同的定義。 – 2010-11-19 18:38:57

回答

1

我個人使用NHibernate with Spring.NET,它支持AOP,所以我基本上定義了一個外部配置文件,這是我希望在SQL事務下執行的方法。那些通常是我的服務方法,它可能會調用我希望在單個事務中運行的多種數據訪問方法。

我認爲事務管理是一個橫切的問題,不應該與數據訪問代碼混合在一起,因爲它會污染它。 Spring.NET負責生成運行時代理並注入適當的事務處理代碼。

+0

謝謝,我真的應該考慮一個簡單的模式:當你想添加類似於裝飾器pettern到方法的東西時,很有可能你真的想模擬AOP。 – v00d00 2010-11-19 18:46:25

1

我使用LINQ to Entities,它爲我處理事務。我想用T4模板添加自動日誌會很容易。

0

除非我弄錯了,否則我認爲您可以假設一個實現IDbTransaction接口的交易對象將在調用Commit方法之前處置的情況下執行回滾。當然,這不是保證,但我認爲如果不這樣實施,這將是一個糟糕的實施。

鑑於此,我只想寫你的例子如下所示:

 using (var tx = connection.BeginTransaction()) 
     { 
      DoWork1(); 
      DoWork2(); 
      DoWork3(); 
      tx.Commit(); 
     } 

,如果我需要捕捉和記錄數據庫異常,那麼我會敷用塊全在一個try/catch:

 try 
     { 
      using (var tx = connection.BeginTransaction()) 
      { 
       DoWork1(); 
       DoWork2(); 
       DoWork3(); 
       tx.Commit(); 
      } 
     } 
     catch (DataException ex) 
     { 
      // log ex 
     }