首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> 關於.NET

深入解析 System.Transactions 事務機制(上):核心類型與可提交事務

     編輯:關於.NET

在 .NET 1.x 時代,開發人員主要透過 ADO.NET 針對單一資料庫連線實作本地事務。隨著 .NET 2.0 的釋出,微軟引入了全新的事務程式設計模型——System.Transactions。所有相關的類型與組件均定義於 System.Transactions 命名空間,這套模型支援顯式(使用 Transaction 類別)與隱式(使用 TransactionScope)兩種事務編程方式。本文將分上、下兩篇,詳細剖析其核心架構與實作細節。

一、 核心類型:System.Transactions.Transaction

在 System.Transactions 體系中,事務本身由 System.Transactions.Transaction 類別表示。該類別標記為 [Serializable] 並實作 ISerializable 介面,意味著事務物件可被序列化。這項特性對 WCF 分散式事務至關重要:事務必須能跨服務邊界傳播,而序列化正是傳播的前提。

1. 事務參與者的登記

Transaction 類別提供五個 EnlistXxx 方法,用於將資源管理器登記至目前事務:

  • EnlistDurable:針對持久化資源管理器(如資料庫)。
  • EnlistVolatile:針對易失性資源管理器(如記憶體資料)。
  • EnlistPromotableSinglePhase:針對可提升的資源管理器(如 SQL Server 2005/2008),支援事務提升機制。

登記的目的是建立事務提交樹,讓根節點的事務管理器能在提交時沿樹狀結構通知所有參與者。不同的提交協定(2PC、SPC)對參與者介面有不同要求:IEnlistmentNotification 對應 2PC,ISinglePhaseNotification 對應 SPC,而 IPromotableSinglePhaseNotification 則支援提升。

2. 環境事務

Transaction.Current 靜態屬性(可讀寫)代表目前執行緒的「環境事務」,儲存於 TLS (Thread Local Storage) 中,故僅對當前執行緒有效。非同步呼叫不會自動傳播環境事務,若需將非同步作業納入事務,需使用相依事務。許多資源管理器(如 SQL Server、Oracle、MSMQ)具備「環境事務感知」能力,會自動登記至 Transaction.Current 所指的事務。

3. 事務識別碼

TransactionInformation 屬性提供事務基本資訊:

  • CreationTime、Status(Active/Committed/Aborted/InDoubt)。
  • LocalIdentifier:本地識別碼,格式為 LTM_GUID:序號。
  • DistributedIdentifier:分布式事務提升後產生的全域 GUID,隨事務跨邊界傳播,常用於稽核追蹤。

Transaction 類別無公用建構子,且僅提供 Rollback 方法,無 Commit。這是因為分散式事務中,只有最初發起事務的參與者才能提交,我們稱之為可提交事務;後續登記的參與者則持有相依事務。

二、 可提交事務

CommittableTransaction 繼承自 Transaction 並實作 IAsyncResult,提供三個公用建構子:

  • 無參數:使用預設逾時 1 分鐘(可透過 <system.transactions> 組態調整)。
  • TimeSpan timeout:指定逾時時間。
  • TransactionOptions options:同時指定逾時與隔離等級。

1. 逾時與隔離等級設定

組態範例:

<system.transactions>
  <defaultSettings timeout="00:01:00" />
  <machineSettings maxTimeout="00:10:00" />
</system.transactions>

預設逾時不得超過機器允許的最大逾時。隔離等級有 7 種,預設為 Serializable(最高隔離),依序降序為 RepeatableRead、ReadCommitted、ReadUncommitted、Snapshot、Chaos、Unspecified。

2. 事務提交

支援同步 Commit() 與非同步 BeginCommit/EndCommit。建立 CommittableTransaction 後,必須手動指派給 Transaction.Current 才會成為環境事務,進而讓感知型資源管理器自動登記。

3. 實戰範例:銀行轉帳

使用兩個預存程序 P_WITHDRAW(扣款)與 P_DEPOSIT(存款),搭配 DbAccessUtil 工具類呼叫。未使用事務時,轉入帳戶不存在會導致扣款成功但存款失敗,資料不一致。引入 CommittableTransaction 後,將兩步操作包裝於同一事務,失敗時自動回滾,確保 ACID 特性。

private static void Transfer(string accountFrom, string accountTo, double amount) {
    Transaction originalTransaction = Transaction.Current;
    CommittableTransaction transaction = new CommittableTransaction();
    try {
        Transaction.Current = transaction;
        Withdraw(accountFrom, amount);
        Deposite(accountTo, amount);
        transaction.Commit();
    } catch (Exception ex) {
        transaction.Rollback(ex);
        throw;
    } finally {
        Transaction.Current = originalTransaction;
        transaction.Dispose();
    }
}

下一篇將深入探討 DependentTransaction 與 TransactionScope。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved