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

C# 資料存取上下文模式:實現 Connection 與 Transaction 的透明管理

     編輯:關於C語言

問題:隱式耦合導致的擴充困境

傳統資料存取方法常在內部自行建立/關閉 SqlConnection 與 SqlTransaction:

public void UpdateOrder(Order order) 
{
    using (var conn = new SqlConnection(connStr))
    using (var cmd = conn.CreateCommand())
    {
        conn.Open();
        cmd.CommandText = "UPDATE Orders SET ...";
        cmd.ExecuteNonQuery();
    }
}

public void UpdateOrderDetails(List<OrderDetail> details) 
{
    using (var conn = new SqlConnection(connStr)) // 另一個連線!
    using (var cmd = conn.CreateCommand())
    {
        conn.Open();
        // ...
    }
}

當業務邏輯需要 UpdateOrder 與 UpdateOrderDetails 在同一交易中執行時,必須大幅重構方法簽名,傳遞 conn、tran 參數,違反開放封閉原則。

解決方案:DataContext / Unit of Work 模式

引入環境上下文物件,由呼叫端控制連線與交易生命週期,資料存取方法僅從上下文取得連線:

核心介面設計

public interface IDataContext : IDisposable
{
    IDbConnection Connection { get; }
    IDbTransaction Transaction { get; }
    void Commit();
    void Rollback();
}

public class SqlDataContext : IDataContext
{
    public IDbConnection Connection { get; private set; }
    public IDbTransaction Transaction { get; private set; }

    public SqlDataContext(string connectionString)
    {
        Connection = new SqlConnection(connectionString);
        Connection.Open();
    }

    public void BeginTransaction()
    {
        Transaction = Connection.BeginTransaction();
    }

    public void Commit() => Transaction?.Commit();
    public void Rollback() => Transaction?.Rollback();

    public void Dispose()
    {
        Transaction?.Dispose();
        Connection?.Dispose();
    }
}

資料存取方法改造

public class OrderRepository
{
    private readonly IDataContext _ctx;

    public OrderRepository(IDataContext ctx) => _ctx = ctx;

    public void UpdateOrder(Order order)
    {
        using (var cmd = _ctx.Connection.CreateCommand())
        {
            cmd.Transaction = _ctx.Transaction;
            cmd.CommandText = "UPDATE Orders SET Status=@Status WHERE Id=@Id";
            // 參數設定...
            cmd.ExecuteNonQuery();
        }
    }

    public void UpdateDetails(List<OrderDetail> details)
    {
        using (var cmd = _ctx.Connection.CreateCommand())
        {
            cmd.Transaction = _ctx.Transaction;
            // 批次處理...
        }
    }
}

業務邏輯層協調交易

public class OrderService
{
    private readonly string _connStr;

    public void ProcessOrder(Order order, List<OrderDetail> details)
    {
        using (var ctx = new SqlDataContext(_connStr))
        {
            ctx.BeginTransaction();
            try
            {
                var repo = new OrderRepository(ctx);
                repo.UpdateOrder(order);
                repo.UpdateDetails(details);
                ctx.Commit();
            }
            catch
            {
                ctx.Rollback();
                throw;
            }
        }
    }
}

進階:巢狀上下文與隱式上下文

  • 巢狀支援:DataContext 可實作參考計數,內層 using 僅增加計數,最外層 Dispose 才真正關閉連線
  • 隱式上下文:搭配 AsyncLocal<IDataContext> 或 CallContext,實現 AmbientContext 模式,方法完全無參數即可取得當前連線(類似 Entity Framework 的 DbContext)

優勢總結

維度傳統內建連線上下文模式
交易邊界控制分散在各方法集中在業務邏輯層
方法複用性低(簽名固定)高(無連線參數)
測試性難以 Mock易於注入測試雙件
連線池效率頻繁開關單一連線跨多方法
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved