.net

2008-10-22 24 views
123

在C#.Net 2.0中執行事務的最佳做法是什麼?什麼是應該使用的類?有什麼陷阱要留意等所有提交和回滾的東西。我剛剛開始一個項目,在將數據插入數據庫時​​可能需要執行一些事務。任何有關交易的基本內容的反應或鏈接都是受歡迎的。.net

+0

這是一個很好的例子,在.NET中的事務(http://www.codeproject.com/KB/database/transactions.aspx)在codeproject上用作開始。 – 2008-10-22 06:45:13

+2

有用的http://www.codeproject.com/Articles/690136/All-About-TransactionScope – Kiquenet 2013-12-03 19:21:48

回答

235

有兩種主要的交易類型;連接交易和環境交易。連接事務(如SqlTransaction)直接綁定到數據庫連接(例如SqlConnection),這意味着您必須保持傳遞連接 - 在某些情況下可以,但不允許「創建/使用/釋放」用法,並且不允許跨數據庫工作。一個例子(格式化爲空格):

using (IDbTransaction tran = conn.BeginTransaction()) { 
    try { 
     // your code 
     tran.Commit(); 
    } catch { 
     tran.Rollback(); 
     throw; 
    } 
} 

不是太混亂,但僅限於我們的連接「conn」。如果我們想要調用不同的方法,我們現在需要傳遞「conn」。

替代方案是環境交易; .NET 2.0中的新增功能,TransactionScope對象(System.Transactions.dll)允許在一系列操作中使用(適合的提供程序將自動登錄環境事務)。這可以很容易地適應現有的(非事務性)代碼,並且可以與多個提供商交談(儘管如果您與多個提供商交談,DTC將會參與其中)。

例如:這裏

using(TransactionScope tran = new TransactionScope()) { 
    CallAMethodThatDoesSomeWork(); 
    CallAMethodThatDoesSomeMoreWork(); 
    tran.Complete(); 
} 

請注意,這兩種方法可以處理自己的連接(開/使用/關閉/處置),但他們會悄悄地成爲環境事務的一部分,無需我們不必通過任何東西。

如果你的代碼錯誤,Dispose()將會在沒有Complete()的情況下被調用,所以它會被回滾。預期的嵌套等被支持,雖然你不能回滾一個內部交易,但完成外部交易:如果有人不滿意,交易將被中止。

TransactionScope的另一個優點是它不僅僅與數據庫綁定在一起;任何支持事務的提供者都可以使用它。例如WCF。或者甚至有一些與TransactionScope兼容的對象模型(即具有回滾功能的.NET類 - 也許比紀念更容易,儘管我自己從未使用過這種方法)。

總而言之,這是一個非常非常有用的對象。

一些注意事項:

  • 在SQL Server 2000中,一個TransactionScope將立即轉至DTC;這在SQL Server 2005及更高版本中得到了解決,它可以使用LTM(開銷少得多),直到與2個源等進行通信時,它被提升爲DTC。
  • 有一個glitch這意味着你可能需要調整您的連接字符串
+1

http://www.codeguru.com/columns/vb/article.php/c11067 – Kimoz 2008-10-22 06:50:55

1

如果你只是需要它的數據庫相關的東西,一些OR映射器(例如NHibernate)默認情況下開箱即用支持TRANSACTINO。

0

這也取決於你所需要的。對於基本的SQL事務,您可以嘗試在您的代碼中使用BEGIN TRANS和COMMIT TRANS來執行TSQL事務。這是最簡單的方法,但它確實有複雜性,你必須小心地正確提交(和回滾)。

我會使用類似

SQLTransaction trans = null; 
using(trans = new SqlTransaction) 
{ 
    ... 
    Do SQL stuff here passing my trans into my various SQL executers 
    ... 
    trans.Commit // May not be quite right 
} 

任何失敗都會彈出你的權利了using和交易總是會提交或回滾(取決於你告訴它做什麼)。我們面臨的最大問題是確保它始終承諾。使用確保交易範圍有限。

3

您也可以將事務包裝到自己的存儲過程中,並以這種方式處理它,而不是在C#中進行事務處理。

10
protected void Button1_Click(object sender, EventArgs e) 
    { 


     using (SqlConnection connection1 = new SqlConnection("Data Source=.\\SQLEXPRESS;AttachDbFilename=|DataDirectory|\\Database.mdf;Integrated Security=True;User Instance=True")) 
     { 
      connection1.Open(); 

      // Start a local transaction. 
      SqlTransaction sqlTran = connection1.BeginTransaction(); 

      // Enlist a command in the current transaction. 
      SqlCommand command = connection1.CreateCommand(); 
      command.Transaction = sqlTran; 

      try 
      { 
       // Execute two separate commands. 
       command.CommandText = 
       "insert into [doctor](drname,drspecialization,drday) values ('a','b','c')"; 
       command.ExecuteNonQuery(); 
       command.CommandText = 
       "insert into [doctor](drname,drspecialization,drday) values ('x','y','z')"; 
       command.ExecuteNonQuery(); 

       // Commit the transaction. 
       sqlTran.Commit(); 
       Label3.Text = "Both records were written to database."; 
      } 
      catch (Exception ex) 
      { 
       // Handle the exception if the transaction fails to commit. 
       Label4.Text = ex.Message; 


       try 
       { 
        // Attempt to roll back the transaction. 
        sqlTran.Rollback(); 
       } 
       catch (Exception exRollback) 
       { 
        // Throws an InvalidOperationException if the connection 
        // is closed or the transaction has already been rolled 
        // back on the server. 
        Label5.Text = exRollback.Message; 

       } 
      } 
     } 


    }