天天看點

TransactionScope

< DOCTYPE html PUBLIC -WCDTD XHTML StrictEN httpwwwworgTRxhtmlDTDxhtml-strictdtd>

TransactionScope是.Net Framework 2.0滞後,新增了一個名稱空間。它的用途是為資料庫通路提供了一個“輕量級”[差別于:SqlTransaction]的事物。使用之前必須添加對 System.Transactions.dll 的引用。

       下列代碼就是一個正在建立的事務,這個事務自身還封裝了多個資料庫查詢。隻要任意一個 SqlCommand 對象引發異常,程式流控制就會跳出 TransactionScope 的 using 語句塊,随後,TransactionScope 将自行釋放并復原該事務。由于這段代碼使用了 using 語句,是以 SqlConnection 對象和 TransactionScope 對象都将被自動調用Dispose()釋放。由此可見,隻需添加很少的幾行代碼,您就可以建構出一個事務模型,這個模型可以對異常進行處理,執行結束後會自行清理,此外,它還可以對指令的送出或復原進行管理。

//建立TransactionScope

 using (TransactionScope tsCope = new TransactionScope())

 {

   using (SqlConnection cn2005 = new SqlConnection(someSql2005))

   {

     SqlCommand cmd = new SqlCommand(sqlUpdate, cn2005);

     cn2005.Open();

     cmd.ExecuteNonQuery();

   }

   using (SqlConnection cn2005 = new SqlConnection(anotherSql2005))

     SqlCommand cmd = new SqlCommand(sqlDelete, cn2005);

   tsCope.Complete();

 }

   連接配接字元串關鍵字(Enlist)

       SqlConnection.ConnectionString 屬性支援關鍵字 Enlist,該關鍵字訓示 System.Data.SqlClient 是否将檢測事務上下文并自動在分布式事務中登記連接配接。 如果 Enlist=true,連接配接将自動在打開的線程的目前事務上下文中登記。 如果 Enlist=false,SqlClient 連接配接不會與分布式事務進行互動。 Enlist 的預設值為 true。 如果連接配接字元串中未指定 Enlist,若在連接配接打開時檢測到一個,連接配接将自動在分布式事務中登記。  

Server=(local)SQL2005;Database=Northwind;Integrated Security=SSPI;auto-enlist=false

        上面所看到的示例中我們使用了TransactionScope的預設設定。TransactionScope有三種模式:

TransactionScopeOptions 描述 Required 如果已經存在一個事務,那麼這個事務範圍将加入已有的事務。否則,它将建立自己的事務。 RequiresNew 這個事務範圍将建立自己的事務。 Suppress 如果處于目前活動事務範圍内,那麼這個事務範圍既不會加入氛圍事務 (ambient transaction),也不會建立自己的事務。當部分代碼需要留在事務外部時,可以使用該選項。

       您可以在代碼的任何位置上随是檢視是否存在事務範圍,具體方法就是檢視 System.Transactions.Transaction.Current 屬性。如果這個屬性為“null”,說明不存在目前事務。

       若要更改 TransactionScope 類的預設設定,您可以建立一個 TransactionOptions 對象,然後通過它在 TransactionScope 對象上設定隔離級别和事務的逾時時間。TransactionOptions 類有一個 IsolationLevel 屬性,通過這個屬性可以更改隔離級别,例如從預設的可序列化 (Serializable) 改為ReadCommitted,甚至可以改為 SQL Server 2005 引入的新的快照 (Snapshot) 級别。(請記住,隔離級别僅僅是一個建議。大多數資料庫引擎會試着使用建議的隔離級别,但也可能選擇其他級别。)此外,TransactionOptions 類還有一個 TimeOut 屬性,這個屬性可以用來更改逾時時間(預設設定為 1 分鐘)。

       下列代碼中使用了預設的 TransactionScope 對象及其預設構造函數。也就是說,它的隔離級别設定為可序列化 (Serializable),事務的逾時時間為 1 分鐘,而且 TransactionScopeOptions 的設定為 Required。

TransactionOptions tOpt = new TransactionOptions();

//設定TransactionOptions模式

tOpt.IsolationLevel = IsolationLevel.ReadCommitted;

// 設定逾時間隔為2分鐘,預設為60秒

tOpt.Timeout = new TimeSpan(0, 2, 0);

string cnString = ConfigurationManager.ConnectionStrings["sql2005DBServer"].ConnectionString);

using (TransactionScope tsCope = new TransactionScope(TransactionScopeOption.RequiresNew, tOpt))

{

  using (SqlConnection cn2005 = new SqlConnection(cnString)

  {

    SqlCommand cmd = new SqlCommand(updateSql1, cn2005);

    cn2005.Open();

    cmd.ExecuteNonQuery();

  }

  tsCope.Complete();

}

        嵌套應用

      如下列代碼,假設 Method1 建立一個 TransactionScope,針對一個資料庫執行一條指令,然後調用 Method2。Method2 建立一個自身的 TransactionScope,并針對一個資料庫執行另一條指令。      

private void Method1()

  using (TransactionScope ts =

    new TransactionScope(TransactionScopeOption.Required))

    using (SqlConnection cn2005 = new SqlConnection())

    {

      SqlCommand cmd = new SqlCommand(updateSql1, cn2005);

      cn2005.Open();

      cmd.ExecuteNonQuery();

    }

    Method2();

    ts.Complete();

private void Method2()

    new TransactionScope(TransactionScopeOption.RequiresNew))

      SqlCommand cmd = new SqlCommand(updateSql2, cn2005);

       總結:

       進入和退出事務都要快,這一點非常重要,因為事務會鎖定寶貴的資源。最佳實踐要求我們在需要使用事務之前再去建立它,在需要對其執行指令前迅速打開連接配接,執行動作查詢 (Action Query),并盡可能快地完成和釋放事務。在事務執行期間,您還應該避免執行任何不必要的、與資料庫無關的代碼,這能夠防止資源被毫無疑義地鎖定過長的時間。

本文轉自 netcorner 部落格園部落格,原文連結:   http://www.cnblogs.com/netcorner/archive/2010/11/10/2911986.html,如需轉載請自行聯系原作者