系统操作日志设计(二)
????? 通了解《系統(tǒng)操作日志設(shè)計(jì)》,已基本明確我們不能通過clone的方式來做日志的設(shè)計(jì),因?yàn)檫@樣不僅會(huì)造成的你數(shù)據(jù)庫表爆炸的情況,還大大的增加了工作量,減少了系統(tǒng)的可維護(hù)性。
????? 通過思考大概清楚系統(tǒng)操作日志的設(shè)計(jì),以下是其UML圖:
?
通過上圖,我們可以了解知道該UML主要由三個(gè)表組成,其中一個(gè)主表LogSetting和兩個(gè)從表分別是LogOperation和LogSettingDetail。
那么怎么樣才能通過這樣的設(shè)計(jì)來現(xiàn)實(shí)我們的日志功能呢?
其實(shí)一開始我就覺得通過.net的反射功能可以很簡單、很方便的實(shí)現(xiàn)這個(gè)功能,所以我就順著一個(gè)思路來實(shí)現(xiàn)她;通過反射動(dòng)態(tài)的獲取Model實(shí)體的屬性,然后再根據(jù)LogSettingDetail配置來匹配所要記錄的字段信息。
?
先來主要的代碼吧,發(fā)現(xiàn)將思想用文字表達(dá)出來還是較困難的,代碼比較直接:
代碼的實(shí)現(xiàn)
usingSystem;usingSystem.Data;usingSystem.Configuration;usingSystem.Web;usingSystem.Web.Security;usingSystem.Web.UI;usingSystem.Web.UI.WebControls;usingSystem.Web.UI.WebControls.WebParts;usingSystem.Web.UI.HtmlControls;usingBLL.Sys;usingSystem.Collections.Generic;usingSystem.Collections.Specialized;usingSystem.Text;usingSystem.Reflection;/// <summary> ///LogManager 的摘要說明/// </summary>public classLogManager<T>whereT :new() {#regionConstructor/// <summary>///日志管理構(gòu)造函數(shù)/// </summary>publicLogManager(){tableName =typeof(T).Name;Model.Sys.LogSettingmodel = 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 newArgumentNullException("日志設(shè)置為空!");}}/// <summary>//////日志管理構(gòu)造函數(shù)/// </summary>/// </summary>/// <param name="tableName">表名</param>/// <param name="businessName">業(yè)務(wù)名稱</param>publicLogManager(stringtableName,stringbusinessName){this.tableName = tableName;this.businessName = businessName;Model.Sys.LogSettingmodel = GetLogSetting(tableName, businessName);if(model !=null){logID = model.LogID;primaryKey = model.PrimaryKey;urlTemplate = model.UrlTemplate;deleteScriptTemplate = model.DeleteScriptTemplate;updateScriptTemplate = model.UpdateScriptTemplate;}else{throw newArgumentNullException("日志設(shè)置為空!");}}#endregion#regionPropertiesprivate intlogID;private stringtableName;private stringbusinessName;private stringprimaryKey;private stringurlTemplate;private stringdeleteScriptTemplate;private stringupdateScriptTemplate;/// <summary>///日志設(shè)置實(shí)體列表/// </summary>publicList<Model.Sys.LogSetting> LogSettingList{get{System.Web.Caching.Cachecache =HttpRuntime.Cache;List<Model.Sys.LogSetting> list = cache["LogSettingList"]asList<Model.Sys.LogSetting>;if(list !=null&& list.Count > 0){returnlist;}else{LogSettingbll =newLogSetting();list = bll.GetModelList(string.Empty);cache["LogSettingList"] = list;returnlist;}}set{System.Web.Caching.Cachecache =HttpRuntime.Cache;cache["LogSettingList"] =null;}}/// <summary>///日志設(shè)置明細(xì)/// </summary>publicList<Model.Sys.LogSettingDetail> LogSettingDetail{get{System.Web.Caching.Cachecache =HttpRuntime.Cache;List<Model.Sys.LogSettingDetail> list = cache["LogSettingDetail"]asList<Model.Sys.LogSettingDetail>;if(list !=null&& list.Count > 0){returnlist;}else{LogSettingDetailbll =newLogSettingDetail();list = bll.GetModelList(string.Empty);cache["LogSettingDetail"] = list;returnlist;}}set{System.Web.Caching.Cachecache =HttpRuntime.Cache;cache["LogSettingDetail"] =null;}}#endregion#regionMethod/// <summary>///通過logId獲取日志設(shè)置明細(xì)/// </summary>/// <param name="logId">日志設(shè)置編號</param>/// <returns></returns>privateList<Model.Sys.LogSettingDetail> GetLogSettingDetails(intlogId){if(logId == 0)throw newArgumentNullException("LogID為空");List<Model.Sys.LogSettingDetail> list =newList<Model.Sys.LogSettingDetail>();foreach(Model.Sys.LogSettingDetailvarinLogSettingDetail){if(var.LogID == logId)list.Add(var);}returnlist;}/// <summary>///通過tableName和businessName來獲取日志設(shè)置對象/// </summary>/// <param name="tableName"></param>/// <param name="businessName"></param>/// <returns></returns>privateModel.Sys.LogSettingGetLogSetting(stringtableName,stringbusinessName){foreach(Model.Sys.LogSettingvarinLogSettingList){if(var.TableName.Equals(tableName,StringComparison.InvariantCultureIgnoreCase) && var.BusinessName.Equals(businessName,StringComparison.InvariantCultureIgnoreCase))returnvar;}return null;}privateModel.Sys.LogSettingGetLogSetting(stringtableName){foreach(Model.Sys.LogSettingvarinLogSettingList){if(var.TableName.Equals(tableName,StringComparison.InvariantCultureIgnoreCase))returnvar;}return null;}/// <summary>///比較兩個(gè)實(shí)體,然后返回實(shí)體中每個(gè)屬性值不同的內(nèi)容/// </summary>/// <param name="oldObj"></param>/// <param name="newObj"></param>/// <returns></returns>public stringCompare(T oldObj, T newObj){TypeobjTye =typeof(T);StringBuildersbResult =newStringBuilder();stringtableHeader ="<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>";stringtableRow ="<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);inti = 1;foreach(Model.Sys.LogSettingDetailvarinlist){PropertyInfoproperty = objTye.GetProperty(var.ColumnName);if(property !=null&& !property.IsSpecialName){objecto = property.GetValue(oldObj,null);objectn = 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>");#regionAdd Log Recordif(i > 1){Model.Sys.LogOperationoperModel =newModel.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)){PropertyInfop = objTye.GetProperty(primaryKey);objecto = p.GetValue(newObj,null);if(o !=null){operModel.PrimaryKeyValue = o.ToString();if(urlTemplate.Contains("{0}"))operModel.Url =string.Format(urlTemplate, o.ToString());}}LogOperationoperBll =newLogOperation();operBll.Add(operModel);}#endregionreturntableHeader + sbResult.ToString();}/// <summary>///刪除實(shí)體操作,這里并不是真的刪除該實(shí)體,而是將刪除的操作記錄在日志中/// </summary>/// <param name="obj"></param>/// <returns></returns>public stringDelete(T obj){TypeobjTye =typeof(T);StringBuildersbResult =newStringBuilder();stringtableHeader ="<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>";stringtableRow ="<tr class='{0}'><td>{1}</td><td>{2}</td><td>{3}</td><td>{4}</td></tr>";List<Model.Sys.LogSettingDetail> list = GetLogSettingDetails(logID);inti = 1;foreach(Model.Sys.LogSettingDetailvarinlist){PropertyInfoproperty = objTye.GetProperty(var.ColumnName);if(property !=null&& !property.IsSpecialName){objecto = property.GetValue(obj,null);sbResult.AppendFormat(tableRow, i % 2 == 0 ?"odd":"even", i, var.ColumnName, var.ColumnText, o);i++;}}sbResult.Append("</table>");#regionAdd Log Record Model.Sys.LogOperationoperModel =newModel.Sys.LogOperation();operModel.LogID = logID;operModel.OperationType = (int)OperationType.Delete;operModel.Content = tableHeader + sbResult.ToString();operModel.CreateTime =DateTime.Now;if(!string.IsNullOrEmpty(primaryKey)){PropertyInfop = objTye.GetProperty(primaryKey);objecto = 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;LogOperationoperBll =newLogOperation();operBll.Add(operModel);#endregionreturn string.Empty;}/// <summary>///添加實(shí)體,將添加的操作記錄在日志中/// </summary>/// <param name="obj"></param>/// <returns></returns>public stringAdd(T obj){TypeobjTye =typeof(T);StringBuildersbResult =newStringBuilder();stringtableHeader ="<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>";stringtableRow ="<tr class='{0}'><td>{1}</td><td>{2}</td><td>{3}</td><td>{4}</td></tr>";List<Model.Sys.LogSettingDetail> list = GetLogSettingDetails(logID);inti = 1;foreach(Model.Sys.LogSettingDetailvarinlist){PropertyInfoproperty = objTye.GetProperty(var.ColumnName);if(property !=null&& !property.IsSpecialName){objecto = property.GetValue(obj,null);sbResult.AppendFormat(tableRow, i % 2 == 0 ?"odd":"even", i, var.ColumnName, var.ColumnText, o);i++;}}sbResult.Append("</table>");#regionAdd Log Record Model.Sys.LogOperationoperModel =newModel.Sys.LogOperation();operModel.LogID = logID;operModel.OperationType = (int)OperationType.Add;operModel.Content = tableHeader + sbResult.ToString();operModel.CreateTime =DateTime.Now;if(!string.IsNullOrEmpty(primaryKey)){PropertyInfop = objTye.GetProperty(primaryKey);objecto = 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;LogOperationoperBll =newLogOperation();operBll.Add(operModel);#endregionreturn string.Empty;}/// <summary>///復(fù)制一個(gè)對象/// </summary>/// <param name="obj"></param>/// <returns></returns>publicT Clone(T obj){TypeobjTye =typeof(T);T model =newT();PropertyInfo[] properties = objTye.GetProperties();foreach(PropertyInfopropertyinproperties){if(!property.IsSpecialName){objecto = property.GetValue(obj,null);property.SetValue(model, o,null);}}returnmodel;}private boolIsEqual(TypedataType,objectoldObj,objectnewObj){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;}elsereturnoldObj.Equals(newObj);}#regionScript. 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 enumOperationType{Select = 0,Add = 1,Update = 2,Delete = 3 }?
使用的場景
Model文件:
publicclassEmployeeModel{publicintID{get;set;}publicstringName{get;set;}…} 下面介紹如何將系統(tǒng)操作日志集成到你的業(yè)務(wù)系統(tǒng)中 添加操作: EmployeeBll bll = new EmployeeBll(); EmployeeModel model = new EmployeeModel(); /* model 實(shí)體經(jīng)過漫長的 賦值 后… */ bll.Add(model); //添加實(shí)體 //添加系統(tǒng)操作記錄 //日志LogManager<EmployeeModel> log =newLogManager<EmployeeModel>(); log.Add(model); ? 更新操作: EmployeeBll bll = new EmployeeBll(); EmployeeModel model = bll.GetModel(employeeID); LogManager<EmployeeModel> log =newLogManager<EmployeeModel>(); EmployeeModel modelOld = log.Clone(model); //克隆EmployeeModel實(shí)體對象,這個(gè)主要是在系統(tǒng)操作日志記錄時(shí)使用的 ? /* model 實(shí)體又經(jīng)過漫長的 賦值 后… */ bll.Update(model); //更新實(shí)體 //將更新的內(nèi)容寫入系統(tǒng)操作日志中 log.Compare(modelOld, model); //原來的實(shí)體和賦值后的實(shí)體對比,并將更新的內(nèi)容寫入系統(tǒng)操作日志中 ? 刪除操作: 在GridView的RowDeleting事件中獲取要?jiǎng)h除的實(shí)體 EmployeeBll bll = new EmployeeBll(); EmployeeModel model = bll.GetModel(employeeID); bll.Delete(employeeID); LogManager<EmployeeModel> log =newLogManager<EmployeeModel>(); log.Delete(model); //實(shí)體的內(nèi)容記錄到日志中 ? .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; }??
總結(jié):
大家可以看到代碼還是比較粗糙的,有不少的重復(fù)的代碼,下一節(jié)將會(huì)討論如何進(jìn)行系統(tǒng)操作日志管理。
另外如何大家有什么意見或想法請分享提出。
?
本節(jié)用到的知識點(diǎn):
1、泛型
2、反射
3、緩存
?
優(yōu)點(diǎn):
1、使用和集成方便,代碼量小;
2、大大提高工作效率,避免表爆炸;
?
缺點(diǎn):
1、代碼有待優(yōu)化;
2、可擴(kuò)展性較差
?
?
轉(zhuǎn)載[http://samlin.cnblogs.com/]轉(zhuǎn)載于:https://www.cnblogs.com/jackljf/archive/2010/07/20/3589396.html
總結(jié)
以上是生活随笔為你收集整理的系统操作日志设计(二)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: join 方法代码实例
- 下一篇: 【转】2010全球最值得模仿的230个网