系统操作日志设计-代码实现
2015-12-06 17:36
736 查看
通了解《系统操作日志设计》,已基本明确我们不能通过clone的方式来做日志的设计,因为这样不仅会造成的你数据库表爆炸的情况,还大大的增加了工作量,减少了系统的可维护性。
通过思考大概清楚系统操作日志的设计,以下是其UML图:
通过上图,我们可以了解知道该UML主要由三个表组成,其中一个主表LogSetting和两个从表分别是LogOperation和LogSettingDetail。
那么怎么样才能通过这样的设计来现实我们的日志功能呢?
其实一开始我就觉得通过.net的反射功能可以很简单、很方便的实现这个功能,所以我就顺着一个思路来实现她;通过反射动态的获取Model实体的属性,然后再根据LogSettingDetail配置来匹配所要记录的字段信息。
先来主要的代码吧,发现将思想用文字表达出来还是较困难的,代码比较直接:
");
#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();
}
///
/// 删除实体操作,这里并不是真的删除该实体,而是将删除的操作记录在日志中
///
///
///
public string Delete(T obj)
{
Type objTye = typeof(T);
StringBuilder sbResult = new StringBuilder();
string tableHeader = "";
tableHeader += "";
string tableRow = "";
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("
");
#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;
}
///
/// 添加实体,将添加的操作记录在日志中
///
///
///
public string Add(T obj)
{
Type objTye = typeof(T);
StringBuilder sbResult = new StringBuilder();
string tableHeader = "";
tableHeader += "";
string tableRow = "";
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("
");
#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.U
ea6f
rl = 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;
}
///
/// 复制一个对象
///
///
///
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文件:
.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode
pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00;
} .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }
大家可以看到代码还是比较粗糙的,有不少的重复的代码,下一节将会讨论如何进行系统操作日志管理。
另外如何大家有什么意见或想法请分享提出。
本节用到的知识点:
1、泛型
2、反射
3、缓存
优点:
1、使用和集成方便,代码量小;
2、大大提高工作效率,避免表爆炸;
缺点:
1、代码有待优化;
2、可扩展性较差
转载请注明出处[http://samlin.cnblogs.com/]
通过思考大概清楚系统操作日志的设计,以下是其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; /// /// LogManager 的摘要说明 /// public class LogManager where T : new() { #region Constructor /// /// 日志管理构造函数 /// 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("日志设置为空!"); } } /// /// /// 日志管理构造函数 /// /// /// 表名 /// 业务名称 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; /// /// 日志设置实体列表 /// 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 4000 ; } } set { System.Web.Caching.Cache cache = HttpRuntime.Cache; cache["LogSettingList"] = null; } } /// /// 日志设置明细 /// 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 /// /// 通过logId获取日志设置明细 /// /// 日志设置编号 /// 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; } /// /// 通过tableName和businessName来获取日志设置对象 /// /// /// /// 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; } /// /// 比较两个实体,然后返回实体中每个属性值不同的内容 /// /// /// /// public string Compare(T oldObj, T newObj) { Type objTye = typeof(T); StringBuilder sbResult = new StringBuilder(); string tableHeader = ""; tableHeader += ""; string tableRow = ""; 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("
序号 | 字段 | 名称 | 旧值 | 新值 |
---|---|---|---|---|
{1} | {2} | {3} | {4} | {5} |
#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();
}
///
/// 删除实体操作,这里并不是真的删除该实体,而是将删除的操作记录在日志中
///
///
///
public string Delete(T obj)
{
Type objTye = typeof(T);
StringBuilder sbResult = new StringBuilder();
string tableHeader = "";
tableHeader += "";
string tableRow = "";
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("
序号 | 字段 | 名称 | 值 |
---|---|---|---|
{1} | {2} | {3} | {4} |
#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;
}
///
/// 添加实体,将添加的操作记录在日志中
///
///
///
public string Add(T obj)
{
Type objTye = typeof(T);
StringBuilder sbResult = new StringBuilder();
string tableHeader = "";
tableHeader += "";
string tableRow = "";
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("
序号 | 字段 | 名称 | 值 |
---|---|---|---|
{1} | {2} | {3} | {4} |
#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.U
ea6f
rl = 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;
}
///
/// 复制一个对象
///
///
///
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 log = new LogManager();
log.Add(model);
更新操作:
EmployeeBll bll = new EmployeeBll();
EmployeeModel model = bll.GetModel(employeeID);
LogManager log = new LogManager();
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 log = new LogManager(); log.Delete(model); //实体的内容记录到日志中
.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode
pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00;
} .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }
总结:
大家可以看到代码还是比较粗糙的,有不少的重复的代码,下一节将会讨论如何进行系统操作日志管理。另外如何大家有什么意见或想法请分享提出。
本节用到的知识点:
1、泛型
2、反射
3、缓存
优点:
1、使用和集成方便,代码量小;
2、大大提高工作效率,避免表爆炸;
缺点:
1、代码有待优化;
2、可扩展性较差
转载请注明出处[http://samlin.cnblogs.com/]
相关文章推荐
- selenium python (十)浏览器多窗口处理
- 有理数类 Java
- 单链表(c语言版)
- theano 编程技巧
- c#从控制台输入年月,控制台输出当月日历。
- 编译原理 LR(0)项目集规范族的构造 LR(0)分析表+分析语句 详解分析+代码
- Arduino 平台与C语言程序设计-week1-Arduino Environment-Lesson3
- Operating System-Thread(5)弹出式线程&&使单线程代码多线程化会产生那些问题
- Spring 自动装配 Bean
- C++学习知识点总结(1)
- 【java】多线程
- ASP.NET WebForm 的CheckBoxList控件通过js获取Value值问题
- nyoj 517 最小公倍数 【java睑板】
- Spring 主配置文件详解
- C#VSVB殊途同归
- javac - Java programming language compiler
- 如何用Python实现八大排序算法
- c++动态联编与静态联编
- 第十二章 并发编程
- python--格式化打印杨辉三角(format)