新世代交易管理機制~System.Transactions

 

新世代交易管理機制~System.Transactions

Transaction交易處理在嚴謹度較高的應用程式必備的基本功能,傳統.NET處理交易有兩種途徑,一是使用ADO.NET為主的SqlTransaction,另一就是透過Enterprise Services(COM+)來達成,那新世代的交易機制還提供了另一種更優的選擇,就是System.Transaction。
--------------------------------------------------------------------------------

【本文內容及程式碼引用聖殿祭司ASP.NET 3.5新書】
在一開始撰寫【新世代交易管理機制~System.Transactions】這章時,我足足焦慮心煩了三天,因為不知道該如何下筆談這章,不是程式面的問題,而是"脈絡",如果我無法告訴讀者說System.Transaction交易管理機制創造的由來,還有使用它的目的,即使貼了一堆實作的程式碼,我個人也會認為是沒用的知識,是失敗的作品,程式不怕不會寫,因為可抄可參考的太多了,但可怕的是,無法辨證程式運用場合是否正確?是否為合理的運用?擺了一堆莫名奇妙的Code在自己的專案中,自已又說不出的所以然,我想這才是為日後問題發生時,埋下一個致命因素,好再我看了很多國外專家的文章,了解System.Transaction創造的起源,再加上我自己的研究心得,最後這星期終於完成了System.Transactions的寫作主題,以下開始是介紹。


傳統.NET1.x的交易程式機制有兩種:
(1)ADO.NET明確交易,指SqlTransaction。
(2)Enterprise Services的宣告式交易兩種。

然而本章所要談的主角不是以上兩者,而是System.Transactions新世代的交易管理機制,System.Transactions是一個命名空間,而裡面包含許多和交易有關的類別,但要說明為什麼要發明System.Transactions這個東西之前,就要先解釋傳統(1)ADO.NET明確交易(2)Enterprise Services的宣告式交易的缺點及侷限性:
(1)ADO.NET明確交易
ADO.NET明確交易效能最快,吃系統資源最少,但是功能過份簡單,只能管理單一物件和單一持久資源間的交易,也就是它只能應付單一SqlConnection對單一SQL Server之間的交易管理(或是Oracle),而無法應付多個SqlConnection對多個SQL Server間的分散式交易。
(2)Enterprise Services的宣告式交易
Enterprise Services的宣告式交易透過COM+型式來提供交易服務,並且需要用到MSDTC(Microsoft Distributed Transaction Coordinator)來協調分散式交易,交易功能最為強大,但是會付出較為昂貴的成本代價,而交易執行的速度最慢。

註:
MSDTC之所以較慢與使用成本較大有兩個主要原因:
1.    因為MSDTC與你的應用程式分處於不同的Process行程。而不同行程在溝通時就會涉及訊息的序列化與反序列化的動作,因而造成CPU及Memory等額外的成本。
2.    MSDTC必須要整合交易中所有的Resource Manager,包含跨AppDomain、跨Processes、跨Machines。各會可以想像當現實世界中,若你需要協調一群人的動作或意見時,有時即便是簡單的工作,中間的過程都可能是沒有效率的,甚至等待回應時間也是很漫長的。

因此各位可以體會到傳統交易程式是一種極端的二分法選擇,明確交易優點是速度快、吃資源少,每個Programmer都想要,但缺點是功能太簡單,也是每個Programmer都想提升的;那Enterprise Services的宣告式交易功能最強,也許能力上比較沒有可挑剔的,但是速度上又快不起來。故綜合以上兩點,可想而知Programmer心中會有多麼地掙扎,為什麼.NET不給我一個執行速度既快,功能又強的交易管理機制?好比男仕選擇女友或老婆時,一位美麗但不富有,另一位富有但不美麗,不知男仕心中會不有極度掙扎!?若這時出現了第三位,既美麗又富有,我想應該男仕也沒什麼好掙扎了,當然挑第三位。

    相同的狀況也發生在Transaction程式的世界,傳統的兩種方法優缺點都過份極端,為了調合這種不完美,微軟推出了System.Transactions新世代的交易管理機制(或稱程式撰寫模型),它屬於輕量級的交易管理機制,執行速度可以和SqlTransaction之類的程式媲美,另一方面可以動態決定是否需要從Local Transaction升級成分散式交易間,最後達到的效能與功能的平衡點,總算讓人覺得還有另一個不錯的選擇。

而System.Transactions交易是屬於輕量級交易管理者(Lightweight Transaction Manager),對於交易程式的撰寫模型有兩個:(1)隱含交易程式撰寫模型,使用TransactionScope類別來建立,(2)明確交易程式撰 寫模型,使用Transaction或CommitableTransation類別來建立,System.Transactions可以從Local transaction交易視需要升級為Distributed Transaction分散式交易,這是最大的目的。

例如使用TransactionScope類別所建立的隱含交易程式:

    1 //宣告TransationScope隱含交易

    2 using (TransactionScope ts = newTransactionScope())

    3 {

    4     string connString = WebConfigurationManager.ConnectionStrings["NorthwindConnectionString"].ConnectionString;

    5     SqlConnection conn = newSqlConnection(connString);

    6     conn.Open();

    7

    8     string strSQL = "INSERT INTO Employees(FirstName, LastName, City, Address) values (@paramFirstName,@paramLastName,@paramCity,@paramAddress)";

    9     SqlCommand cmd = newSqlCommand(strSQL, conn); 

   10

   11     try

   12     {

   13         cmd.Parameters.Add("@paramFirstName", SqlDbType.NVarChar, 20).Value = txtFirstName.Text;

   14         cmd.Parameters.Add("@paramLastName", SqlDbType.NVarChar, 10).Value = txtLastName.Text;

   15         cmd.Parameters.Add("@paramCity", SqlDbType.NVarChar, 15).Value = txtCity.Text;

   16         cmd.Parameters.Add("@paramAddress", SqlDbType.NVarChar, 60).Value = txtAddress.Text;

   17         cmd.ExecuteNonQuery();

   18         txtMsg.Text = "新增資料成功,交易確認!";

   19         ts.Complete();

   20     }

   21     catch

   22     {

   23         txtMsg.Text = "新增資料失敗,交易Rollback!";

   24     }

   25

   26     finally

   27     {

   28         conn.Close();

   29         conn.Dispose();

   30         cmd.Dispose();

   31     }

   32 }

使用CommittableTransaction類別所建立的明確交易程式:

    1 //宣告CommittableTransaction明確交易

    2 using (CommittableTransaction tran = newCommittableTransaction())

    3 {

    4     string connString = WebConfigurationManager.ConnectionStrings["NorthwindConnectionString"].ConnectionString;

    5     SqlConnection conn = newSqlConnection(connString);

    6     conn.Open();

    7     conn.EnlistTransaction(tran); //登記加入明確交易

    8

    9     string strSQL = "INSERT INTO Employees(FirstName, LastName, City, Address) values (@paramFirstName,@paramLastName,@paramCity,@paramAddress)";

   10     SqlCommand cmd = newSqlCommand(strSQL, conn);     

   11

   12     try

   13     {

   14         cmd.Parameters.Add("@paramFirstName", SqlDbType.NVarChar, 20).Value = txtFirstName.Text;

   15         cmd.Parameters.Add("@paramLastName", SqlDbType.NVarChar, 10).Value = txtLastName.Text;

   16         cmd.Parameters.Add("@paramCity", SqlDbType.NVarChar, 15).Value = txtCity.Text;

   17         cmd.Parameters.Add("@paramAddress", SqlDbType.NVarChar, 60).Value = txtAddress.Text;

   18         cmd.ExecuteNonQuery();

   19         txtMsg.Text = "新增資料成功,交易確認!";

   20         throw new Exception("想反悔了,取消Insert!!!");

   21         tran.Commit();  //確認交易

   22     }

   23     catch

   24     {

   25         txtMsg.Text = "新增資料失敗,交易Rollback!";

   26         tran.Rollback();  //回復交易

   27     }

   28

   29     finally

   30     {

   31         conn.Close();

   32         conn.Dispose();

   33         cmd.Dispose();

   34     }

   35 }

最後,學會了TransactionScope隱含交易及CommittableTransaction明確交易程式之撰寫,不過那並不是最主要之重點,而真正的重點卻是來自於LTM的特質,LTM在面對交易管理時,若可以在Local Transaction完成的,絕不會非得使用分散式交易管理,如此可達到成本與速度兼優的好處,而當Local Transaction不能應付交易時,則它又可以具備提升到分散式交易的延展性,並且不需要Programmer涉入太多的交易管理細節。

原文地址:https://www.cnblogs.com/zitjubiz/p/1229146.html