C#——細說事務(上)


引言

其實事務在數據層、服務層、業務邏輯層多處地方都會使用到,在本篇文章將會為大家一一細說。

前面三節是事務的基礎,主要介紹事務的由來以及事務管理器的總體結構,分別講述輕量級事務管理器(LTM)、核心事務管理器(KTM)、分布式事務協調器(DTC)的差別。並介紹Framework里事務類System.Transactioins.Transaction 的方法與屬性,講解在ADO.NET中事務的常用使用方式。

由於時間倉促,文章有錯漏的地方歡迎各位點評。

 

目錄

一、事務的定義

二、事務管理器

三、在ADO.NET中實現事務

四、隱式事務 TransactionScope

五、在WCF中實現事務

六、嵌套式事務

七、異步事務

一、事務的定義

事務:明確指定事務的開始,connection需要打開方可使用,默認為closed,即:顯示調用con.BeginTransaction()

隱式事務:無法明確指定事務的開始,默認connection已被打開為open 

分布式隱式事務:使用TransactionScope類

分布式顯式事務:使用CommittableTransaction類,con.EnlistTransaction(Transaction對象)//將連接登記到事務

所 謂事務,它是一個操作集合,這些操作要么都執行,要么都不執行,它是一個不可分割的工作單位。典型的例子就像從網上銀行系統的帳戶A轉帳到帳戶B,它經過 兩個階段:1.從帳戶A取出款項。2.把款項放入帳戶B中。這兩個過程要么同時成功,要么同時失敗,這一系列的操作就被稱為事務性 (Transactional)操作。

在一個事務性操作的環境下,操作有着以下的4種特性,被稱為ACID特性

原子性(Atomicity) 當事務結束,它對所有資源狀態的改變都被視為一個操作,這些操作要不同時成功,要不同時失敗  
一致性(Consistency) 操作完成后,所有數據必須符合業務規則,否則事務必須中止
隔離性(Isolation) 事務以相互隔離的方式執行,事務以外的實體無法知道事務過程中的中間狀態
持久性(Durable) 事務提交后,數據必須以一種持久性方式存儲起來

 

回到目錄


二、事務管理器

在軟件系統當中可以看到無論在數據庫、Web服務、WCF、文件系統都存在着數據參與到事務運作當中,我們把管理這些數據的工具稱為資源管理器 RM(Resources Manager)。而事務管理器TM(Transaction Manager)就是協調多個資源管理器的工作,保證數據完整性的工具。

 由上圖可以看到事務的管理流程,系統通知事務管理器TM來啟動事務,事務管理器TM控制向多個資源管理器RM並協調RM之間的事務操作。圖中存在兩個持久化RM,分別管理數據庫和文件系統,這些事務操作要不同時成功,要不同時失敗。

事務管理器一般分為三類:輕量級事務管理器(LTM)、核心事務管理器(KTM)、分布式事務協調器(DTC)

 

1. 輕量級事務管理器 (LTM)

它 是包括在System.Transactions 命名空間內的一個事務管理框架,它只能管理單個應用程序域內的事務。LTM 可以管理多個易變的RM,但只能管理一個持久化RM。若事務試圖加入第二個持久化RM,那輕量級事務管理器LTM將提升級別。LTM是性能最高的事務管理 器,在可選擇的情況下應該盡可能地使用 LTM 事務管理器。

這里易變RM是指它參與會引發 “未確定狀態” 的2PC事務時候,不需要恢復服務,更多時候,易變RM的數據只存儲在內存當中。

而持久化RM是指它參與會引發 “未確定狀態” 的2PC事務時候,它需要恢復服務,持久化RM管理的數據是在於硬盤當中。所以,參與2PC事務的的持久RM必須有新舊兩個版本,如果事務引發 “未確定狀態” 的時候,那么它就會聯系持久化RM,恢復到其中一個版本。

2PC 是2 Phase Commit的縮寫,代表事務的2階段提交驗證算法:在數據提交時,第一階段:應用程序記錄每個數據源並執行更新請求,TM通知每個RM來執行分布式事 務,然后每個RM都對數據執行本地的事務,在事務將提交前,TM會與各個RM進行信息交換,以獲知更新是否成功。第二階段,如果其中任何一個RM表示更新 失敗,TM就會通知所有的RM事務操作失敗,實現數據回滾。如果所有RM的操作都成功,那么整個TM事務就宣告成功。

 

2. 核心事務管理器 (KTM)

KTM是用於Windows Vista和Windows Server 2008 系統中的輕量級事務管理器,與LTM相像,它可以管理多個易變的RM,但只能管理一個持久化RM。

 

3. 分布式事務協調器(DTC)

分 布式事務協調器DTC(Distributed Transaction Coordinator)能管理多個持久化RM中的事務,事務可以跨越應用程序域、進程、硬件、域等所有的邊界。在Windows Server 2008當中,DTC支持OleDB、XA、WS-AtomicTransaction、WSCoordination、WS- BusinessActivity等多個協議。由於分布式事務需要在多個參與方之間實現多次通訊,所以是一種巨大的開銷,因此,在可以使用LTM和KTM的時候,應該盡量避免使用DTC。在上面圖片中的事務同時啟動了兩個RM分別處理數據庫數據與文件數據,當中啟動的就是DTC分布式事務。

 

4.事務類 System.Transactioins.Transaction

Transaction是由Framework 2.0 就開始引入,用於顯示管理事務的一個類。通過Transaction可以直接管理事務的中止、釋放,也可以獲取、克隆當前的環境事務類。

  • Transaction的公用屬性

其中Transaction.Current 比較常用,它可以指向一個當前運行環境中的事務,如果環境事務不存在,系統將返回一個null

Transaction transaction=Transaction.Current;

屬性 說明
Current 獲取或設置環境事務。
IsolationLevel 獲取事務的隔離級別。
TransactionInformation 檢索有關某個事務的附加信息。

 

 

 

 

  • Transaction的常用公用方法

其中Rollback、Dispose方法可以控制事務中止、釋放,而Clone、DependentClone方法在多線程操作中經常用到,在 “異步事務” 一節中將詳細說明

方法 說明
Rollback 中止事務、回滾。
Dispose 釋放事務對象。
Clone     創建事務克隆
DependentClone 創建事務的依賴克隆。

 

 

 

 

  • Transaction的事件

在事務完成后,會觸發TransactionCompleted事件,開發人員可以在此事件的過程監測其狀態

事件 說明
TransactionCompleted 在事務完成后執行

 

 

 

5. 事務狀態 TransactionInformation

上面講解過事務分為本地事務與分布式事務,而Transaction類的TransactionInformation是事務狀態的記錄,它可以跟蹤事務動作,分辨事務現處的狀態,記錄本地事務與分布式事務的Guid。

TransactionInformation有兩個重要成員

 1 public class TransactionInformation
 2 {
 3       //返回分布式事務標識符
4 public Guid DistributedIdentifier 5 {get;} 6 7 //返回本地事務標識符
8 public string LocalIdentifier 9 {get;} 10 }

LocalIndentifier 是本地事務的標識符,它可以獲取本地事務管理器(LTM)的ID,並且注意只要事務存在,它的值就永遠不會是null。它包含兩個部分,一個是LTM的 Guid,它是應用程序中的唯一值,代表了現存應用程序域分配的LTM。另一部分是一個可變量,代表了當時該應用程序域中的事務數量。

例如:3427dec9-4abc-34cc-9edf-30ad835c33k3:3

其中3427dec9-4abc-34cc-9edf-30ad835c33k3是此本地事務管理器的Guid,在事務啟動后,此值都是不變的,而 “3” 代表此刻該應用程序域中存在 “3” 個本地事務。


DistributedIndentifier 是分布式事務的標識符,在普通情況下DistributedIndentifier的值都為Guid.Empty。但當LTM或KTM事務被提升到分布式 事務時,DistributedIndentifier就會產生。最重的是,在同一個分布式事務管理器當中,即使事務跨越服務邊界,分布式ID都是一致 的。DistributedIndentifier是分布式事務的唯一標識符,它的使用方法在后面 “事務的傳播”一節將詳細介紹。

在TransactionManager類中,還提供了一個事件DistributedTransactionStarted專門用於測試分布式事務的變化。

 1     class Program
 2     {
 3         static void Main(string[] args)
 4         {
 5             using (TransactionScope scope = new TransactionScope())
 6             {
 7                 TransactionManager.DistributedTransactionStarted += OnDistributedTransactionStarted;
 8                 ............
 9                 scope.Complete();
10             }
11             Console.ReadKey();
12         }
13 
14         //當執行分布式事務是就會啟動此方法顯示事務信息
15 static void OnDistributedTransactionStarted(object sender, TransactionEventArgs args) 16 { 17 Transaction transaction = args.Transaction; 18 Console.WriteLine("Distributed Transaction Started!\n DistributedIndentifier:" 19 +transaction.TransactionInformation.DistributedIdentifier); 20 } 21 }

基礎知識就先講到這里,下面開始介紹一下事務的具體用法。


三、在ADO.NET中實現事務

1. ADO.NET事務的主要成員

需要使用事務管理的情況很多,在數據層使用得特別廣泛,幾乎每一個系統的數據層都會實現事務。數據層的事務都是繼承自DBTransaction,派生自IDbTransaction的。下面介紹一下IDbTransaction的基本成員:

1 public interface IDbTransaction:IDisposable
2 {
3       IDbConnection Connection {get;}     //返回Connection對象
4 IsolationLevel IsolationLevel{get;} 5 void Commit(); //數據提交,把所有改變數據保存到持久化數據庫
6 void Rollback(); //數據回滾,把所有數據恢復原值
7 }

其 中Connection屬性是返回初始化此事務時所引用的連接對象的。Commit()方法應該在完成所有數據操作后才調用,調用該方法后,已經改變的數 據將會保存到持久化數據庫當中。而Rollback()是出現錯誤時調用的,調用后數據將返回初始值。IsolationLevel是指定遇到其它並行事 務時的處理方式。

ADO.NET當中有多個子類都繼續自DBTransaction,其中SqlTransaction是比較常用 的,SqlTransaction中還定義了一個Save()方法,這個方法允許開發人員把失敗的事務回滾到上一個保存點而不回滾整個事務。而在 DataContext類里面,Transaction屬性會返回DBTransaction對象。

2.開發實例

在傳統的ADO.NET中使用事務,方法如下:

 1 private static void Execute(string connectionString)
 2 {
 3     using (SqlConnection connection = new SqlConnection(connectionString))
 4     {
 5         connection.Open();
 6 
 7         SqlCommand command = connection.CreateCommand();
 8         SqlTransaction transaction;
 9 
10         //啟動事務
11 transaction = connection.BeginTransaction("SampleTransaction"); 12 13 //設定SqlCommand的事務和連接對象
14 command.Connection = connection; 15 command.Transaction = transaction; 16 17 try 18 { 19 command.CommandText ="Insert into ......"; 20 command.ExecuteNonQuery(); 21 22 // 完成提交
23 transaction.Commit(); 24 ...... 25 } 26 catch (Exception ex) 27 { 28 //數據回滾
29 transaction.Rollback(); 30 ..... 31 } 32 } 33 }

在DataContext中使用事務,方法極其相似,不同的是SqlCommand中事務為SqlTransaction,在DataContext中事務為DbTransaction

 1  using(MyDataContext context=new MyDataContext())
 2  {
 3       try
 4       {
 5           context.Connection.Open();
 6           context.Transaction=context.Connection.BeginTransaction();
 7           //更新數據
8 ......... 9 context.SubmitChanges(); 10 //事務提交
11 context.Transaction.Commit(); 12 } 13 catch(Excetion ex) 14 { 15 //數據回滾
16 context.Transaction.Rollback(); 17 //錯誤處理
18 ......... 19 } 20 }


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM