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

Winform框架核心技術:一行代碼實現業務表操作日志全自動审計

     編輯:關於.NET

業務系統中,關鍵表的增刪改操作審計是合規與數據安全的剛需。本文揭秘Winform開發框架如何通過「基類事件驅動 + 實體攜帶用戶上下文 + 差異化內容比對」的組合拳,讓業務模塊僅需在BLL構造函數註冊一行事件綁定代碼,即可獲得完整、可讀、可追溯的操作日志能力。

一、 數據訪問層(DAL)繼承體系與事件定義

框架構建 AbstractBaseDAL<T> 作為所有數據庫訪問類的超級基類,在其中定義操作日志委托與事件:

public delegate bool OperationLogEventHandler(string userId, string tableName, string operationType, string note, DbTransaction trans = null);

public abstract class AbstractBaseDAL<T> where T : BaseEntity, new() {
    public event OperationLogEventHandler OnOperationLog; // 操作日志事件
    // ...
}

DAL繼承關系圖

二、 底層觸發機制:封裝統一調用入口

在 Insert、Update、Delete 等核心方法中,調用統一封裝的日志觸發方法(以更新為例):

public virtual bool Update(T obj, object primaryKeyValue, DbTransaction trans = null) {
    ArgumentValidation.CheckForNullReference(obj, "傳入的對象obj為空");
    OperationLogOfUpdate(obj, primaryKeyValue, trans); // 觸發日志記錄
    Hashtable hash = GetHashByEntity(obj);
    return Update(primaryKeyValue, hash, trans);
}

protected virtual void OperationLogOfUpdate(T obj, object id, DbTransaction trans = null) {
    if (OnOperationLog != null) {
        string operationType = "修改";
        string userId = obj.CurrentLoginUserId; // 關鍵:從實體獲取操作人
        Hashtable recordField = GetHashByEntity(obj);
        Dictionary<string, string> dictColumnNameAlias = GetColumnNameAlias();
        
        T objInDb = FindByID(id, trans); // 讀取數據庫舊值
        if (objInDb != null) {
            Hashtable dbrecordField = GetHashByEntity(objInDb);
            StringBuilder sb = new StringBuilder();
            foreach (string field in recordField.Keys) {
                string newValue = recordField[field].ToString();
                string oldValue = dbrecordField[field].ToString();
                if (newValue != oldValue) { // 僅記錄變更字段
                    string columnAlias = "";
                    if (dictColumnNameAlias.TryGetValue(field, out columnAlias) && !string.IsNullOrEmpty(columnAlias)) {
                        columnAlias = string.Format("({0})", columnAlias); // 附帶中文別名
                    }
                    sb.AppendLine(string.Format("{0}{1}:", field, columnAlias));
                    sb.AppendLine(string.Format("\t {0} -> {1}", oldValue, newValue));
                    sb.AppendLine();
                }
            }
            string note = sb.ToString();
            OnOperationLog(userId, this.tableName, operationType, note, trans); // 拋出事件
        }
    }
}

三、 關鍵設計亮點:實體基類攜帶操作人上下文

避免在海量業務方法簽名中添加 userId 參數,框架在 BaseEntity 中引入非持久化屬性 CurrentLoginUserId:

[DataContract]
public class BaseEntity {
    private string m_CurrentLoginUserId;
    [DataMember]
    public string CurrentLoginUserId {
        get { return m_CurrentLoginUserId; }
        set { m_CurrentLoginUserId = value; }
    }
}

業務層調用前僅需賦值:entity.CurrentLoginUserId = LoginUserInfo.ID;,底層自動捕獲,零侵入式傳遞操作人身份。

四、 業務層(BLL)事件處理與持久化

權限系統建立專表 T_ACL_OperationLog 存儲審計記錄。BLL基類中封裝靜態處理方法 OperationLog.OnOperationLog,自動豐富用戶IP、MAC、公司等上下文信息:


OperationLogInfo info = new OperationLogInfo();
info.TableName = tableName;
info.OperationType = operationType;
info.Note = note;
info.CreateTime = DateTime.Now;
if (!string.IsNullOrEmpty(userId)) {
    UserInfo userInfo = BLLFactory<User>.Instance.FindByID(userId, trans);
    if (userInfo != null) {
        info.User_ID = userId;
        info.LoginName = userInfo.Name;
        info.FullName = userInfo.FullName;
        info.Company_ID = userInfo.Company_ID;
        info.CompanyName = userInfo.CompanyName;
        info.MacAddress = userInfo.CurrentMacAddress;
        info.IPAddress = userInfo.CurrentLoginIP;
    }
}
return BLLFactory<OperationLog>.Instance.Insert(info, trans);

操作日志表結構

五、 業務模塊接入:僅需一行註冊

以機構管理(OU)模塊為例,構造函數中綁定事件即可啟用全自動審計:


public class OU : BaseBLL<OUInfo> {
    public OU() : base() {
        base.Init(this.GetType().FullName, System.Reflection.Assembly.GetExecutingAssembly().GetName().Name);
        // 一行代碼接入操作日志
        baseDal.OnOperationLog += new OperationLogEventHandler(WHC.Security.BLL.OperationLog.OnOperationLog);
        this.ouDal = baseDal as IOU;
    }
}

六、 框架級配置與界面展示

權限模塊提供可視化配置界面,支持按表名、操作類型篩選日志,雙擊查看字段級變更明細,並可配置哪些表啟用審計。

操作日志主界面

日志明細字段對比

審計參數配置界面

七、 總結

該方案通過「基類事件定義 + 實體上下文傳遞 + 差異化比對 + 統一持久化」四層架構,將審計能力下沉至框架核心,業務開發零感知接入,兼顧性能(僅記錄變更字段)與可讀性(含中文別名),是企業級框架治理數據安全的典範實踐。

Winform開發框架功能總覽

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