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

C# Attribute 實現 AOP 事務(五):TransactionAop 實作 IMessageSink、SyncProcessMessage 建立交易上下文、Commit/Rollback 自動管理、效能與架構優化建議

     編輯:關於C語言

TransactionAop 核心實作


public sealed class TransactionAop : IMessageSink
{
    private readonly IMessageSink _nextSink;
    public TransactionAop(IMessageSink nextSink) { _nextSink = nextSink; }

    public IMessageCtrl AsyncProcessMessage(IMessage msg, IMessageSink replySink) => null;

    public IMessageSink NextSink => _nextSink;

    public IMessage SyncProcessMessage(IMessage msg)
    {
        IMethodCallMessage call = msg as IMethodCallMessage;
        if (call == null || Attribute.GetCustomAttribute(call.MethodBase, typeof(TransactionMethodAttribute)) == null)
            return _nextSink.SyncProcessMessage(msg); // 無標記,直接傳遞

        // 有標記,建立交易
        using (var conn = new SqlConnection(Configurations.SQLSERVER_CONNECTION_STRING))
        {
            conn.Open();
            var trans = conn.BeginTransaction();
            CallContext.SetData(ContextName, trans); // 存入上下文

            IMessage retMsg = _nextSink.SyncProcessMessage(msg); // 執行目標方法

            if (trans != null)
            {
                var returnMsg = retMsg as IMethodReturnMessage;
                if (returnMsg?.Exception != null)
                    trans.Rollback(); // 發生例外回滾
                else
                    trans.Commit();   // 正常提交
                trans.Dispose();
            }
            return retMsg;
        }
    }

    public static string ContextName => "TransactionAop";
}

效能與架構優化建議

  1. AOP 方式比手動 try-catch-Commit/Rollback 效能稍低,但可維護性、易用性大幅提升。
  2. SqlDAL 繼承 ContextBoundObject 會增加上下文切換開銷。替代方案:SqlDAL 改為普通類別,透過屬性取得 CallContext 交易,避免繼承開銷。

private SqlDAL _sqlDao;
public SqlDAL SqlDao
{
    get
    {
        if (_sqlDao == null)
        {
            _sqlDao = new SqlDAL();
            object obj = CallContext.GetData(TransactionAop.ContextName);
            if (obj != null && obj is SqlTransaction) _sqlDao.SqlTrans = (SqlTransaction)obj;
        }
        return _sqlDao;
    }
}

持續探索更輕量化方案,歡迎建議。

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