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

C# 透過 COM+ 實作分散式交易控制:跨資料庫自動回滾

     編輯:關於C語言

問題背景

單一資料庫交易易處理 (ADO.NET Transaction),但**跨多個資料庫** (或異構資料來源) 的原子性操作,需分散式交易協調器 (DTC/MSDTC)。COM+ (Enterprise Services) 提供宣告式分散式交易支援。

架構流程

  1. 建立**強名稱簽署**的類別庫專案。
  2. 類別繼承 ServicedComponent,標記 [Transaction(TransactionOption.Required)]。
  3. 組件標記 [assembly: ApplicationActivation(ActivationOption.Server)] (啟動為 COM+ 應用程式)。
  4. 編譯 → regsvcs.exe Assembly.dll 註冊至 COM+ 目錄。
  5. 用戶端參考組件建立實例呼叫,COM+ 執行期自動登記 DTC 交易。

伺服端元件實作


using System;
using System.EnterpriseServices;
using System.Data.SqlClient;
using System.Reflection;

[assembly: ApplicationActivation(ActivationOption.Server)]
[assembly: ApplicationName("DistributedTxDemo")]
[assembly: Description("跨資料庫分散式交易示範")]

namespace ComPlusTxDemo
{
    [Transaction(TransactionOption.Required)] // 必須在交易內執行
    public class OrderProcessor : ServicedComponent
    {
        private const string ConnStr1 = "Server=.;Database=PubDB;User=sa;Password=...;";
        private const string ConnStr2 = "Server=.;Database=Northwind;User=sa;Password=...;";

        public void PlaceOrder(string customerId, string productId, int qty)
        {
            try
            {
                // DB 1: 扣庫存
                ExecuteNonQuery(ConnStr1,
                    "UPDATE Inventory SET Qty = Qty - @qty WHERE ProductId = @pid",
                    ("@qty", qty), ("@pid", productId));

                // DB 2: 建訂單 (故意寫錯欄位名稱模擬失敗)
                ExecuteNonQuery(ConnStr2,
                    "INSERT INTO Orders (CustomerId, ProductId, Qty, BadColumn) VALUES (@cid, @pid, @qty, 1)",
                    ("@cid", customerId), ("@pid", productId), ("@qty", qty));

                // 兩步皆成功,交易自動 Commit
                ContextUtil.SetComplete(); // 明確標記完成 (非必要,正常返回即 Commit)
            }
            catch (Exception ex)
            {
                // 任何例外,標記 Abort → 所有資料庫 Rollback
                ContextUtil.SetAbort();
                throw new EnterpriseServicesException("分散式交易失敗,已回滾", ex);
            }
        }

        private void ExecuteNonQuery(string connStr, string sql, params (string name, object value)[] parameters)
        {
            using (var conn = new SqlConnection(connStr))
            using (var cmd = new SqlCommand(sql, conn))
            {
                foreach (var (name, value) in parameters)
                    cmd.Parameters.AddWithValue(name, value);
                conn.Open();
                cmd.ExecuteNonQuery();
            }
        }
    }
}

組件強名稱簽署


// 開發人員命令提示字元
sn -k KeyPair.snc
// 專案屬性 → 簽署 → 勾選「為組件簽署」 → 選擇 KeyPair.snc
// 或 AssemblyInfo.cs: [assembly: AssemblyKeyFile(@"..\..\KeyPair.snc")]

註冊至 COM+


// 管理員權限命令提示字元
regsvcs ComPlusTxDemo.dll
// 成功會在「元件服務」→「COM+ 應用程式」看到 DistributedTxDemo

用戶端呼叫


using ComPlusTxDemo;

var processor = new OrderProcessor();
try
{
    processor.PlaceOrder("CUST001", "PROD001", 5);
    Console.WriteLine("訂單建立成功,跨庫交易 Commit");
}
catch (Exception ex)
{
    Console.WriteLine($"失敗:{ex.Message}");
}

關鍵點總結

項目說明
TransactionOption.Required呼叫者有交易則加入,無則建立新交易
ApplicationActivation.Server在獨立 dllhost.exe 進程執行,隔離度高、支援遠端呼叫
ContextUtil.SetAbort()標記交易失敗,觸發所有登記資源管理器 Rollback
ContextUtil.SetComplete()標記成功 (正常返回同效),提早釋放資源
SqlConnection 登記ADO.NET SqlConnection 自動偵測 COM+ 交易上下文並登記 DTC

現代化替代:System.Transactions + TransactionScope


using System.Transactions;

using (var scope = new TransactionScope(TransactionScopeOption.Required))
{
    using (var c1 = new SqlConnection(connStr1))
    using (var c2 = new SqlConnection(connStr2))
    {
        c1.Open(); c2.Open(); // 自動登記 DTC (若連線字串 Enlist=true)
        // ... 執行 SQL ...
    }
    scope.Complete(); // Commit
} // Dispose 時若未 Complete → Rollback

TransactionScope ( .NET 2.0+ ) 取代 COM+ 成為**慣用分散式交易寫法**,無需強名稱/註冊/COM+ 部署,程式碼更簡潔。但需確保 MSDTC 服務啟用、防火牆開放 135/動態埠、連線字串 Enlist=true (預設)。

適用場景比較

  • COM+ / ServicedComponent: 既有 COM+ 架構、需物件共用/物件池/角色型安全/事件發佈訂閲、跨進程/跨機器遠端呼叫。
  • TransactionScope: 現代 .NET 應用、微服務、ASP.NET Core、容器化部署、程式碼優先、無 COM 相依。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved