.Net 事務

在分佈式應用程序中,不可避免地會常用到事務控制。事務有一個開頭和一個結尾,它們指定了事務的邊界,事務在其邊界以內能夠跨越進程和計算機。事務邊界內的全部資源都參與同一個事務。要維護事務邊界內資源間的一致性,事務必須具有 ACID 屬性,即原子性、一致性、隔離性和持續性。
 
1.本地事務和分佈式事務html

 

  本地事務是其範圍爲單個可識別事務的數據資源的事務(例如,Microsoft SQL Server 數據庫或 MSMQ 消息隊列)。例如,當單個數據庫系統擁有事務中涉及的全部數據時,就能夠遵循 ACID 規則。在 SQL Server 的狀況下,由內部事務管理器來實現事務的提交和回滾操做。
  分佈式事務能夠跨越不一樣種類的可識別事務的數據資源,而且能夠包括多種操做(例如,從 SQL 數據庫檢索數據、從 Message Queue Server 讀取消息以及向其餘數據庫進行寫入)。經過利用跨若干個數據資源來協調提交和停止操做以及恢復的軟件,能夠簡化分佈式事務的編程。Microsoft Distributed Transaction Coordinator (DTC) 就是一種這樣的技術。它採用一個二階段的提交協議,該協議可確保事務結果在事務中涉及的全部數據資源之間保持一致。DTC 只支持已實現了用於事務管理的兼容接口的應用程序。這些應用程序被稱爲資源管理器(有關此主題的詳細信息,請參見 .NET Framework Developer's Guide 中的 Distributed Transactions <http://msdn.microsoft.com/library/en-us/cpguide/html/cpconDistributedTransactions.asp>; ),目前存在許多這樣的應用程序,包括 MSMQ、Microsoft SQL Server、Oracle、Sybase 等等。 

2.數據庫事務數據庫

 

 

若是調用一個在 BEGIN TRANSACTION 和 COMMIT/ROLLBACK TRANSACTION 語句中封裝了所需操做的存儲過程,您就能夠在到數據庫服務器的單個往返行程中運行事務,從而實現最佳性能。數據庫事務還支持嵌套事務,這意味着您能夠從一個活動事務中啓動一個新事務。下面的代碼片段中,BEGIN TRANSACTION 語句開始了一個新事務。能夠經過使用 COMMIT TRANSACTION 語句將更改提交到數據庫來結束事務,或者,在發生任何錯誤的狀況下,經過使用 ROLLBACK TRANSACTION 語句將全部更改撤消來結束事務:編程

 

 

 

**//// <summary>
        /// SQL事務:
        /// </summary>
        public void SQLTran()
        {
            SqlConnection conn = new SqlConnection("Data Source=127.0.0.1;Initial Catalog=Northwind;Persist Security Info=True;User ID=sa;Password=123;");
            SqlCommand cmd = new SqlCommand();
            cmd.CommandText = "SPTransaction";
            cmd.CommandType = CommandType.StoredProcedure;
            cmd.Connection = conn;
            conn.Open();
            SqlParameter[] paras= new SqlParameter[]{
             new SqlParameter ("@UpdateID",SqlDbType.Int,32),
             new SqlParameter ("@UpdateValue",SqlDbType .NChar,50),
             new SqlParameter ("@InsertID",SqlDbType.Int ,32),
             new SqlParameter ("@InsertValue",SqlDbType.NChar ,50)};
            paras[0].Value = "2";
            paras[1].Value = "Update Value1";
            paras[2].Value = "6";
            paras[3].Value = "Insert Value1";
            foreach (SqlParameter para in paras )
            {
                cmd.Parameters.Add(para);
            }
            cmd.ExecuteNonQuery();   
        }

 

3.手動事務緩存

 

利用手動事務,您可使用開始和結束事務的顯式指令來顯式控制事務邊界。此模式還支持容許您從活動事務中開始一個新事務的嵌套事務。可是,應用此控制會給您增長一種額外負擔,您須要向事務邊界登記數據資源並對這些資源進行協調。因爲對分佈式事務沒有任何內置的支持,所以,若是您選擇以手動方式來控制分佈式事務,將承擔許多責任;您須要控制每一個鏈接和資源登記,並經過提供實現來保持事務的 ACID 屬性。  安全

 

ADO.NET 手動事務  服務器

 

這兩種 Microsoft ADO.NET 數據提供程序經過提供建立到數據存儲區的鏈接、開始一個事務、提交或停止事務以及最後關閉鏈接的一組對象來啓用手動事務。咱們將以 ADO.NET SQL 託管提供程序爲例來進行說明。在單個事務中執行操做,您須要建立 SQLTransaction 對象、使用 SQLConnection 對象開始事務、確保在事務內進行數據庫交互以及提交或停止事務。SQLTransaction 對象提供了多種方法和屬性來控制事務。若是事務中的每一個操做都已經成功完成,可使用 「提交」 方法將所作的更改提交到數據庫。使用 SQLTransaction 對象的 「回滾」 方法能夠回滾更改。意 "命令" 對象的 Transaction 屬性必須設置爲一個已經開始的事務,這樣,它才能在該事務中執行。網絡

SQLConnection Conn = New SQLConnection("ConnString"); 
SQLCommand Cmd = New SQLCommand; 
// Open a connection 
Conn.Open(); 
// Begin a transaction 
SQLTransaction Txn = Conn.BeginTransaction();
// Set the Transaction in which the command executes 
Cmd.Transaction = Txn; 

 

MSMQ 手動事務  app

 

.NET Framework 以兩種不一樣的方式支持 MSMQ 事務:經過容許多個消息做爲事務的一部分發送或接收而手動(內部)支持;經過參與 Distributed Transaction Coordinator (DTC) 事務而自動(外部)支持。MSMQ 手動事務是經過 MessageQueueTransaction 類來支持的,而且徹底在 MSMQ 引擎內處理。有關詳細信息,請參見 Duncan Mackenzie 的文章 Reliable Messaging with MSMQ and .NET <http://msdn.microsoft.com/library/en-us/dnbda/html/bdadotnetasync2.asp>;async

4.自動事務分佈式

 

.NET Framework 依靠 MTS/COM+ 服務來支持自動事務。COM+ 使用 Microsoft Distributed Transaction Coordinator (DTC) 做爲事務管理器和事務協調器在分佈式環境中運行事務。這樣可以使 .NET 應用程序運行跨多個資源結合不一樣操做(例如,將定單插入 SQL Server 數據庫、將消息寫入 Microsoft 消息隊列 (MSMQ) 隊列、發送電子郵件以及從 Oracle 數據庫檢索數據)的事務。 過提供基於聲明性事務的編程模型,COM+ 使應用程序能夠很容易地運行跨不一樣種類的資源的事務。這種作法的缺點是,因爲存在 DTC 和 COM 互操做性開銷,致使性能下降,並且不支持嵌套事務。

ASP.NET 頁、Web Service 方法和 .NET 類經過設置聲明性事務屬性均可以標記爲事務性。  

 

a.ASP.NET: <@ Page Transaction="Required">

 

 

b.ASP.NET Web 服務 
<%@ WebService Language="VB" class="Class1" %> 
<%@ assembly name="System.EnterpriseServices" %>

 

Public Class Class1 Inherits WebService

 

<WebMethod(TransactionOption := TransactionOption.RequiresNew)> _

 

Public Function Method1()

 

… 
c.要參與自動事務,.NET 類必須是從 System.EnterpriseServices.ServicedComponent 類繼承的,這可以使得該 .NET 類可以在 COM+ 內運行。在這個過程當中,要將 COM+ 與 DTC 進行交互以建立一個分佈式事務,也要登記後臺的全部資源鏈接。您還須要對該類設置聲明性事務屬性以肯定其事務性行爲。

 

[Transaction(TransactionOption.Required)] 

public class Class1 : ServicedComponent { 

//… 

 

 

類的事務屬性能夠設置爲如下任何選項: 
• 「禁用」 
— 指示該對象從不在 COM+ 事務中建立。該對象能夠直接使用 DTC 來得到事務性支持。
• NotSupported 
— 指示該對象從不在事務中建立。 
• 「支持」 
— 指示該對象在其建立者的事務的上下文中運行。若是該對象自己是根對象,或者其建立者不在事務中運行,則該對象將在不使用事務的狀況下建立。
• 「必選」 
— 指示對象在其建立者的事務的上下文中運行。若是該對象自己是根對象,或者其建立者不在事務中運行,則該對象將使用一個新事務來建立。 
• RequiresNew 
— 指示該對象須要一個事務,而且該對象使用新事務來建立。  

 

下面的代碼顯示了配置爲在 COM+ 中運行、將程序集屬性設置爲配置 COM+ 應用程序屬性的 .NET 類。

using System;
using System.Runtime.CompilerServices; 
using System.EnterpriseServices;
using System.Reflection; 
//Registration details. 
//COM+ application name as it appears in the COM+ catalog 
[Assembly: ApplicationName("Class1")] 
'Strong name for assembly 
[Assembly: AssemblyKeyFileAttribute("class1.snk")] 
[Assembly: ApplicationActivation(ActivationOption.Server)] 
[Transaction(TransactionOption.Required)] 
public class Class1 : ServicedComponent { 
[AutoComplete] 
public void Example1() 

//… 




指定要安裝該程序集的組件的 COM+ 應用程序的名稱。 指定 COM+ 應用程序是否爲服務器應用程序或庫應用程序。指定 ApplicationActivation(ActivationOption.Server)時,必須使用 gacutil 命令行工具 (GacUtil.exe) 將程序集安裝到全局程序集緩存 (GAC)。  

 

您可使用 Regsvcs.exe 命令行工具將程序集轉換爲類型庫,並將類型庫註冊和安裝到指定的 COM+ 應用程序中。該工具還可用來配置您已經用編程方式添加到程序集中的屬性。例如,若是在程序集中指定 ApplicationActivation(ActivationOption.Server),該工具將建立一個服務器應用程序。若是在未使用 COM+ 來安裝程序集的狀況下調用程序集,運行時將建立和註冊一個類型庫,並使用 COM+ 來安裝該庫。您能夠在組件服務管理單元中看到和配置爲程序集建立的 COM+ 應用程序。  

 

經過使用System.EnterpriseServices.ContextUtil 類,能夠得到有關 COM+ 對象上下文的信息。它提供SetComplete 和 SetAbort 方法,以便分別顯式提交和回滾事務。正如您預想的那樣,當全部操做已成功執行後,緊隨 try 程序塊的最後調用 ContextUtil.SetComplete 方法來提交事務。所引起的任何異常將在 catch 程序塊中被捕獲,該程序塊使用ContextUtil.SetAbort 停止事務。 

 

您還可使用System.EnterpriseServices.AutoComplete 屬性類來讓服務組件自動選擇是提交事務仍是停止事務。若是方法調用成功返回,組件將傾向於選擇提交事務。若是方法調用引起異常,事務會自動停止;您無需顯式調用 ContextUtilSetAbort。要使用此功能,應在類方法以前插入 <AutoComplete> 屬性:  

[Transaction(TransactionOption.Required)] 
public class Class1 : ServicedComponent { 
[AutoComplete] 
public void Example1() 

//… 



在須要事務跨 MSMQ 和其餘可識別事務的資源(例如,SQL Server 數據庫)運行的系統中,只能使用 DTC 或 COM+ 事務,除此以外沒有其餘選擇。DTC 協調參與分佈式事務的全部資源管理器,也管理與事務相關的操做。  

 

5 TransactionScope事務

  TransactionScope事務類,它可使代碼塊成爲事務性代碼。並自動提高爲分佈式事務
 優勢:實現簡單,同時可以自動提高爲分佈式事務

**//// <summary>
        /// TransactionScope事務:可自動提高事務爲徹底分佈式事務的輕型(本地)事務。 
        /// 使用時要保證MSDTC服務(控制分佈事務)是開啓的可使用:net start msdtc命令開啓服務;
        /// </summary>
        public void ADONetTran2()
        {
             SqlConnection conn = new SqlConnection("Data Source=127.0.0.1;Initial Catalog=Northwind;Persist Security Info=True;User ID=sa;Password=123;");
             SqlCommand cmd = new SqlCommand();
            try
            {
              
                using (System.Transactions.TransactionScope ts = new TransactionScope())
                {
                    
                    cmd.CommandText = "Update Region Set RegionDescription=@UpdateValue where RegionID=@UpdateID";
                    cmd.CommandType = CommandType.Text;
                    cmd.Connection = conn;
                    conn.Open();
                    SqlParameter[] paras = new SqlParameter[]{
                                        new SqlParameter ("@UpdateID",SqlDbType.Int,32),
                                        new SqlParameter ("@UpdateValue",SqlDbType .NChar,50)};
                    paras[0].Value = "2";
                    paras[1].Value = "Update Value12";

                    foreach (SqlParameter para in paras)
                    {
                        cmd.Parameters.Add(para);
                    }
                    cmd.ExecuteNonQuery();


                    cmd.CommandText = "insert into Region values(@InsertID,@InsertValue)";
                    cmd.CommandType = CommandType.Text;

                    paras = new SqlParameter[]{
                                        new SqlParameter ("@InsertID",SqlDbType.Int ,32),
                                        new SqlParameter ("@InsertValue",SqlDbType.NChar ,50)};
                    paras[0].Value = "8";
                    paras[1].Value = "Insert Value";

                    cmd.Parameters.Clear();
                    foreach (SqlParameter para in paras)
                    {
                        cmd.Parameters.Add(para);
                    }

                    cmd.ExecuteNonQuery();
                    //提交事務
                    ts.Complete();
                }
            }
            catch
            {
                throw;
            }
            finally
            {
                conn.Close();
            }

        }

4 COM+事務
  在分佈式應用程序中,每每要同時操做多個數據庫,使用數據庫事務就不能知足業務的要求了。在COM+中,提供完整的事務處理服務。很方便處理多個數據庫上的事務。

/// <summary>
        /// COM+事務
        /// </summary>
        public void ComTran()
        {
            SqlConnection conn = new SqlConnection("Data Source=127.0.0.1;Initial Catalog=Northwind;Persist Security Info=True;User ID=sa;Password=123;");
            SqlCommand cmd = new SqlCommand();
            ServiceConfig sc = new ServiceConfig();

            //指定事務類型
            sc.Transaction = TransactionOption.Required;
            //設置啓動跟蹤
            sc.TrackingEnabled = true;
            //建立一個上下文,該上下文的配置由做爲 cfg 參數傳遞的 ServiceConfig 對象來指定。
            //隨後,客戶端和服務器端的策略均被觸發,如同發生了一個方法調用。
            //接着,新的上下文被推至上下文堆棧,成爲當前上下文
            ServiceDomain.Enter(sc);
            try
            {
                    cmd.CommandText = "Update Region Set RegionDescription=@UpdateValue where RegionID=@UpdateID";
                    cmd.CommandType = CommandType.Text;
                    cmd.Connection = conn;
                    conn.Open();
                    SqlParameter[] paras = new SqlParameter[]{
                                        new SqlParameter ("@UpdateID",SqlDbType.Int,32),
                                        new SqlParameter ("@UpdateValue",SqlDbType .NChar,50)};
                    paras[0].Value = "2";
                    paras[1].Value = "Update Value22";

                    foreach (SqlParameter para in paras)
                    {
                        cmd.Parameters.Add(para);
                    }
                    cmd.ExecuteNonQuery();


                    cmd.CommandText = "insert into Region values(@InsertID,@InsertValue)";
                    cmd.CommandType = CommandType.Text;

                    paras = new SqlParameter[]{
                                        new SqlParameter ("@InsertID",SqlDbType.Int ,32),
                                        new SqlParameter ("@InsertValue",SqlDbType.NChar ,50)};
                    paras[0].Value = "9";
                    paras[1].Value = "Insert Value";

                    cmd.Parameters.Clear();
                    foreach (SqlParameter para in paras)
                    {
                        cmd.Parameters.Add(para);
                    }

                    cmd.ExecuteNonQuery();

                    //提交事務
                    ContextUtil.SetComplete();
            }
            catch
            {
                //回滾事務
                ContextUtil.SetAbort();
                throw;
            }
            finally
            {
                conn.Close();
                //觸發服務器端的策略,隨後觸發客戶端的策略,如同一個方法調用正在返回。
                //而後,當前上下文被彈出上下文堆棧,調用 Enter 時正在運行的上下文成爲當前的上下文。
                ServiceDomain.Leave();
            }
        }

須要特別補充的是:
若是你使用的是分佈事務(TransactionScope事務和COM+事務),在默認狀況下你是要從新配置安裝SQL Server數據庫服務器和訪問數據庫的客戶端的.(若是沒有配置運行會出現如下錯誤:該夥伴事務管理器已經禁止了它對遠程/網絡事務的支持。 (異常來自 HRESULT:0x8004D025)
)下面是MSDN上關於配置分佈式事務的一段原話:
配置分佈式事務
要啓用分佈式事務,可能須要經過網絡啓用 MS DTC,以便在使用應用了最新的 Service Pack 的較新操做系統(例如 Windows XP 或 Windows 2003)時使用分佈式事務。若是啓用了 Windows 防火牆(Windows XP Service Pack 2 的默認設置),必須容許 MS DTC 服務使用網絡或打開 MS DTC 端口。
實際怎麼配置呢,通過個人實際使用:大體以下:打開'控制面板'->'管理工具'->'組件服務',點開'組件服務'->'計算機'->'個人電腦',在'個人電腦'上右擊屬性,點'MSDTC',而後點'安全性配置'。做爲數據庫的服務器的配置以下:

而訪問數據庫的客戶端的配置和服務器端的稍有些差異:


在設置完上面的還有使防火牆MS DTC 服務使用網絡或打開 MS DTC 端口:運行netsh firewall set allowedprogram %windir%\system32\msdtc.exe MSDTC enable命令就能夠了

小結

 

------------------------------------------------------------------------------------------ 
    每一種事務方法都是應用程序性能和代碼可維護性的折衷。運行在存儲過程當中實現的數據庫事務可提供最佳性能,由於它只須要到數據庫的單個往返行程。另外,這種方法還提供了顯式控制事務邊界的靈活性。雖然它提供了良好的性能和靈活性,但您須要用 Transact SQL 來編寫代碼,這就不如用 .NET 來編寫代碼那麼簡單。
    使用 ADO.NET 事務對象的手動事務很易於編寫代碼,並實現了用顯式指令開始和結束事務以控制事務邊界的靈活性。可是,爲得到這種簡易性和靈活性,須要一些完成事務所需的到數據庫的額外往返行程,這致使了性能下降。
    如果事務跨越多個可識別事務的管理器(可能包括 SQL Server 數據庫、MSMQ 消息隊列等等),自動事務將是惟一的選擇。這種方法大大簡化了應用程序設計,減小了編碼需求。不過,因爲 COM+ 服務執行全部協調工做,可能有一些額外的開銷。

相關文章
相關標籤/搜索