• 系统操作日志设计-代码实现(转载)


    通过思考大概清楚系统操作日志的设计,以下是其UML图:

    通过上图,我们可以了解知道该UML主要由三个表组成,其中一个主表LogSetting和两个从表分别是LogOperation和LogSettingDetail。

    那么怎么样才能通过这样的设计来现实我们的日志功能呢?

    其实一开始我就觉得通过.net的反射功能可以很简单、很方便的实现这个功能,所以我就顺着一个思路来实现她;通过反射动态的获取Model实体的属性,然后再根据LogSettingDetail配置来匹配所要记录的字段信息。

    先来主要的代码吧,发现将思想用文字表达出来还是较困难的,代码比较直接:

    代码的实现

    
    
    using System;
    using System.Data;
    using System.Configuration;
    using System.Web;
    using System.Web.Security;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using System.Web.UI.WebControls.WebParts;
    using System.Web.UI.HtmlControls;
    
    using BLL.Sys;
    
    
    using System.Collections.Generic;
    using System.Collections.Specialized;
    using System.Text;
    using System.Reflection;
    /// <summary>
    /// LogManager 的摘要说明
    /// </summary>
    public class LogManager<T> where T : new() 
    {
        #region Constructor
        /// <summary>
        /// 日志管理构造函数
        /// </summary>
        public LogManager()
        {
            tableName = typeof(T).Name;
            Model.Sys.LogSetting model = GetLogSetting(tableName);
            if (model != null)
            {
                businessName = model.BusinessName;
                logID = model.LogID;
                primaryKey = model.PrimaryKey;
                urlTemplate = model.UrlTemplate;
                deleteScriptTemplate = model.DeleteScriptTemplate;
                updateScriptTemplate = model.UpdateScriptTemplate;
            }
            else
            {
                throw new ArgumentNullException("日志设置为空!");
            }
        }
        /// <summary>    /// 
        /// 日志管理构造函数
        /// </summary>
        /// </summary>
        /// <param name="tableName">表名</param>
        /// <param name="businessName">业务名称</param>
        public LogManager(string tableName, string businessName)
        {
            this.tableName = tableName;
            this.businessName = businessName;
    
            Model.Sys.LogSetting model = GetLogSetting(tableName, businessName);
            if (model != null)
            {
                logID = model.LogID;
                primaryKey = model.PrimaryKey;
                urlTemplate = model.UrlTemplate;
                deleteScriptTemplate = model.DeleteScriptTemplate;
                updateScriptTemplate = model.UpdateScriptTemplate;
            }
            else
            {
                throw new ArgumentNullException("日志设置为空!");
            }
        }
        #endregion
    
    
        #region Properties
        private int logID;
        private string tableName;
        private string businessName;
        private string primaryKey;
        private string urlTemplate;
        private string deleteScriptTemplate;
        private string updateScriptTemplate;
    
    
        /// <summary>
        /// 日志设置实体列表
        /// </summary>
        public List<Model.Sys.LogSetting> LogSettingList
        {
            get
            {
                System.Web.Caching.Cache cache = HttpRuntime.Cache;
                List<Model.Sys.LogSetting> list = cache["LogSettingList"] as List<Model.Sys.LogSetting>;
                if (list != null && list.Count > 0)
                {
                    return list;
                }
                else
                {
                    LogSetting bll = new LogSetting();
                    list = bll.GetModelList(string.Empty);
                    cache["LogSettingList"] = list;
                    return list;
                }
            }
            set
            {
                System.Web.Caching.Cache cache = HttpRuntime.Cache;
                cache["LogSettingList"] = null;
            }
        }
        /// <summary>
        /// 日志设置明细
        /// </summary>
        public List<Model.Sys.LogSettingDetail> LogSettingDetail
        {
            get
            {
                System.Web.Caching.Cache cache = HttpRuntime.Cache;
                List<Model.Sys.LogSettingDetail> list = cache["LogSettingDetail"] as List<Model.Sys.LogSettingDetail>;
                if (list != null && list.Count > 0)
                {
                    return list;
                }
                else
                {
                    LogSettingDetail bll = new LogSettingDetail();
                    list = bll.GetModelList(string.Empty);
                    cache["LogSettingDetail"] = list;
                    return list;
                }
            }
            set
            {
                System.Web.Caching.Cache cache = HttpRuntime.Cache;
                cache["LogSettingDetail"] = null;
            }
        }
    
        #endregion
    
        #region Method
        /// <summary>
        /// 通过logId获取日志设置明细
        /// </summary>
        /// <param name="logId">日志设置编号</param>
        /// <returns></returns>
        private List<Model.Sys.LogSettingDetail> GetLogSettingDetails(int logId)
        {
            if (logId == 0)
                throw new ArgumentNullException("LogID为空");
    
            List<Model.Sys.LogSettingDetail> list = new List<Model.Sys.LogSettingDetail>();
            foreach (Model.Sys.LogSettingDetail var in LogSettingDetail)
            {
                if (var.LogID == logId)
                    list.Add(var);
            }
            return list;
        }
        /// <summary>
        /// 通过tableName和businessName来获取日志设置对象
        /// </summary>
        /// <param name="tableName"></param>
        /// <param name="businessName"></param>
        /// <returns></returns>
        private Model.Sys.LogSetting GetLogSetting(string tableName, string businessName)
        {
            foreach (Model.Sys.LogSetting var in LogSettingList)
            {
                if (var.TableName.Equals(tableName, StringComparison.InvariantCultureIgnoreCase) && var.BusinessName.Equals(businessName, StringComparison.InvariantCultureIgnoreCase))
                    return var;
            }
            return null;
        }
        private Model.Sys.LogSetting GetLogSetting(string tableName)
        {
            foreach (Model.Sys.LogSetting var in LogSettingList)
            {
                if (var.TableName.Equals(tableName, StringComparison.InvariantCultureIgnoreCase))
                    return var;
            }
            return null;
        }
    
    
        /// <summary>
        /// 比较两个实体,然后返回实体中每个属性值不同的内容
        /// </summary>
        /// <param name="oldObj"></param>
        /// <param name="newObj"></param>
        /// <returns></returns>
        public string Compare(T oldObj, T newObj)
        {
            Type objTye = typeof(T);
    
            StringBuilder sbResult = new StringBuilder();
            string tableHeader = "<table class="GridView" cellspacing="0" rules="all" border="1" id="gv" style="border-collapse:collapse;">";
            tableHeader += "<tr><th scope="col">序号</th><th scope="col">字段</th><th scope="col">名称</th><th scope="col">旧值</th><th scope="col">新值</th></tr>";
    
            string tableRow = "<tr class='{0}'><td>{1}</td><td>{2}</td><td>{3}</td><td>{4}</td><td>{5}</td></tr>";
    
            List<Model.Sys.LogSettingDetail> list = GetLogSettingDetails(logID);
            int i = 1;
    
            foreach (Model.Sys.LogSettingDetail var in list)
            {
                PropertyInfo property = objTye.GetProperty(var.ColumnName);
                if (property != null && !property.IsSpecialName)
                {
                    object o = property.GetValue(oldObj, null);
                    object n = property.GetValue(newObj, null);
                    if (!IsEqual(property.PropertyType, o, n))
                    {
                        sbResult.AppendFormat(tableRow, i % 2 == 0 ? "odd" : "even", i, var.ColumnName, var.ColumnText, o, n);
                        i++;
                    }
    
                }
            }
    
            sbResult.Append("</table>");
    
            #region Add Log Record
    
            if (i > 1)
            {
                Model.Sys.LogOperation operModel = new Model.Sys.LogOperation();
                operModel.LogID = logID;
                operModel.OperationType = (int)OperationType.Update;
                operModel.Content = tableHeader + sbResult.ToString();
                operModel.CreateTime = DateTime.Now;
                
                
                if (HttpContext.Current != null)
                    operModel.CreateUser = HttpContext.Current.User.Identity.Name;
                if (!string.IsNullOrEmpty(primaryKey))
                {
                    PropertyInfo p = objTye.GetProperty(primaryKey);
                    object o = p.GetValue(newObj, null);
                    if (o != null)
                    {
                        operModel.PrimaryKeyValue = o.ToString();
    
                        if (urlTemplate.Contains("{0}"))
                            operModel.Url = string.Format(urlTemplate, o.ToString());
                    }
    
                }
                LogOperation operBll = new LogOperation();
                operBll.Add(operModel);
    
            }
            #endregion
    
            return tableHeader + sbResult.ToString();
    
        }
        /// <summary>
        /// 删除实体操作,这里并不是真的删除该实体,而是将删除的操作记录在日志中
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public string Delete(T obj)
        {
            Type objTye = typeof(T);
    
    
            StringBuilder sbResult = new StringBuilder();
            string tableHeader = "<table class="GridView" cellspacing="0" rules="all" border="1" id="gv" style="border-collapse:collapse;">";
            tableHeader += "<tr><th scope="col">序号</th><th scope="col">字段</th><th scope="col">名称</th><th scope="col">值</th></tr>";
    
            string tableRow = "<tr class='{0}'><td>{1}</td><td>{2}</td><td>{3}</td><td>{4}</td></tr>";
    
            List<Model.Sys.LogSettingDetail> list = GetLogSettingDetails(logID);
            int i = 1;
            foreach (Model.Sys.LogSettingDetail var in list)
            {
                PropertyInfo property = objTye.GetProperty(var.ColumnName);
                if (property != null && !property.IsSpecialName)
                {
                    object o = property.GetValue(obj, null);
    
                    sbResult.AppendFormat(tableRow, i % 2 == 0 ? "odd" : "even", i, var.ColumnName, var.ColumnText, o);
                    i++;
                }
            }
    
            sbResult.Append("</table>");
    
    
            #region Add Log Record       
    
            Model.Sys.LogOperation operModel = new Model.Sys.LogOperation();
            operModel.LogID = logID;
            operModel.OperationType = (int)OperationType.Delete;
            operModel.Content = tableHeader + sbResult.ToString();
            operModel.CreateTime = DateTime.Now;
            if (!string.IsNullOrEmpty(primaryKey))
            {
                PropertyInfo p = objTye.GetProperty(primaryKey);
                object o = p.GetValue(obj, null);
                if (o != null)
                {
                    operModel.PrimaryKeyValue = o.ToString();
                    if (urlTemplate.Contains("{0}"))
                        operModel.Url = string.Format(urlTemplate, o.ToString());
                }
            }
            if (HttpContext.Current != null)
                operModel.CreateUser = HttpContext.Current.User.Identity.Name;
            LogOperation operBll = new LogOperation();
            operBll.Add(operModel);
    
            #endregion
            return string.Empty;
        }
        /// <summary>
        /// 添加实体,将添加的操作记录在日志中
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public string Add(T obj)
        {
            Type objTye = typeof(T);
    
    
            StringBuilder sbResult = new StringBuilder();
            string tableHeader = "<table class="GridView" cellspacing="0" rules="all" border="1" id="gv" style="border-collapse:collapse;">";
            tableHeader += "<tr><th scope="col">序号</th><th scope="col">字段</th><th scope="col">名称</th><th scope="col">值</th></tr>";
    
            string tableRow = "<tr class='{0}'><td>{1}</td><td>{2}</td><td>{3}</td><td>{4}</td></tr>";
    
            List<Model.Sys.LogSettingDetail> list = GetLogSettingDetails(logID);
            int i = 1;
            foreach (Model.Sys.LogSettingDetail var in list)
            {
                PropertyInfo property = objTye.GetProperty(var.ColumnName);
                if (property != null && !property.IsSpecialName)
                {
                    object o = property.GetValue(obj, null);
    
                    sbResult.AppendFormat(tableRow, i % 2 == 0 ? "odd" : "even", i, var.ColumnName, var.ColumnText, o);
                    i++;
                }
            }
    
            sbResult.Append("</table>");
    
    
            #region Add Log Record      
    
            Model.Sys.LogOperation operModel = new Model.Sys.LogOperation();
            operModel.LogID = logID;
            operModel.OperationType = (int)OperationType.Add;
            operModel.Content = tableHeader + sbResult.ToString();
            operModel.CreateTime = DateTime.Now;
            if (!string.IsNullOrEmpty(primaryKey))
            {
                PropertyInfo p = objTye.GetProperty(primaryKey);
                object o = p.GetValue(obj, null);
                if (o != null)
                {
                    operModel.PrimaryKeyValue = o.ToString();
                    if (urlTemplate.Contains("{0}"))
                        operModel.Url = string.Format(urlTemplate, o.ToString());
                }
            }
            if (HttpContext.Current != null)
                operModel.CreateUser = HttpContext.Current.User.Identity.Name;
            LogOperation operBll = new LogOperation();
            operBll.Add(operModel);
    
            #endregion
            return string.Empty;
        }
        /// <summary>
        /// 复制一个对象
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public T Clone(T obj)
        {
            Type objTye = typeof(T);
            T model = new T();
            
            PropertyInfo[] properties = objTye.GetProperties();
            foreach (PropertyInfo property in properties)
            {
                if(!property.IsSpecialName)
                {
                    object o = property.GetValue(obj, null);
                    property.SetValue(model, o, null);
                }
                
    
            }
            return model;
        }
    
        private bool IsEqual(Type dataType, object oldObj, object newObj)
        {
            if (oldObj == null && newObj == null)
                return true;
    
            if (dataType == typeof(int))
            {
                return (int)oldObj == (int)newObj;
            }
            else if (dataType == typeof(decimal))
            {
                return (decimal)oldObj == (decimal)newObj;
            }
            else if (dataType == typeof(double))
            {
                return (double)oldObj == (double)newObj;
            }
            else if (dataType == typeof(Guid))
            {
                return (Guid)oldObj == (Guid)newObj;
            }
            else if (dataType == typeof(DateTime))
            {
                return (DateTime)oldObj == (DateTime)newObj;
            }
            else
                return oldObj.Equals(newObj);
    
        }
    
        #region Script Excute
    
        //public int DeleteBusRecode(string primaryKeyValue)
        //{
        //    if (string.IsNullOrEmpty(tableName))
        //        throw new ArgumentException("tableName为空");
        //    if(string.IsNullOrEmpty(primaryKey))
        //        throw new ArgumentException("primaryKey为空");
        //    if (string.IsNullOrEmpty(deleteScriptTemplate))
        //        throw new ArgumentException("deleteScriptTemplate为空");
    
        //    string strSql = string.Format(deleteScriptTemplate, primaryKeyValue);
    
        //    Database db = DatabaseFactory.CreateDatabase();
        //    return 0;
    
            
        //}
        #endregion
    
        #endregion
    
    
    }
    public enum OperationType
    {
        Select = 0,
        Add = 1,
        Update = 2,
        Delete = 3
    }
    
    
    

      

     

    使用的场景

    Model文件:

    public class EmployeeModel  {  public int ID{get;set;}  public string Name{get;set;}  …  } 
    下面介绍如何将系统操作日志集成到你的业务系统中
    添加操作:
    EmployeeBll bll = new EmployeeBll();
    EmployeeModel model = new EmployeeModel();
    /* model 实体经过漫长的 赋值 后… */
    bll.Add(model);    //添加实体
    //添加系统操作记录
    //日志 LogManager<EmployeeModel> log = new LogManager<EmployeeModel>();
    log.Add(model);
     
    更新操作:
    EmployeeBll bll = new EmployeeBll();
    EmployeeModel model = bll.GetModel(employeeID);
    LogManager<EmployeeModel> log = new LogManager<EmployeeModel>();
    EmployeeModel modelOld = log.Clone(model);   //克隆EmployeeModel实体对象,这个主要是在系统操作日志记录时使用的
     
    /* model 实体又经过漫长的 赋值 后… */
    bll.Update(model);     //更新实体
    //将更新的内容写入系统操作日志中
    log.Compare(modelOld, model);    //原来的实体和赋值后的实体对比,并将更新的内容写入系统操作日志中
     
    删除操作:
    在GridView的RowDeleting事件中获取要删除的实体
    EmployeeBll bll = new EmployeeBll();
    EmployeeModel model = bll.GetModel(employeeID);
    bll.Delete(employeeID);
    LogManager<EmployeeModel> log = new LogManager<EmployeeModel>(); log.Delete(model);       //实体的内容记录到日志中
     

    总结:

    大家可以看到代码还是比较粗糙的,有不少的重复的代码,下一节将会讨论如何进行系统操作日志管理

    另外如何大家有什么意见或想法请分享提出。

    本节用到的知识点

    1、泛型

    2、反射

    3、缓存

    优点:

    1、使用和集成方便,代码量小;

    2、大大提高工作效率,避免表爆炸;

    缺点:

    1、代码有待优化;

    2、可扩展性较差

  • 相关阅读:
    【转】c#文件操作大全(一)
    Visual Assist安装、破解方法
    web socket多线程实时监听
    SFTP上传下载
    数据库分页代码
    JAVA H5微信分享
    Eclipse中activiti插件的安装
    HTTP请求报文和HTTP响应报文
    CodeVS 1013&1029
    Codeforces 805D/804B
  • 原文地址:https://www.cnblogs.com/sandea/p/3293691.html
Copyright © 2020-2023  润新知