您的位置:首页 > 其它

系统操作日志设计(二)

2010-07-20 18:43 651 查看
上一篇《系统操作日志设计》,已基本介绍了为什么要系统操作日志和设计系统操作日志部分内容,如不清楚系统操作日志的请点这里。:)
通了解《系统操作日志设计》,已基本明确我们不能通过clone的方式来做日志的设计,因为这样不仅会造成的你数据库表爆炸的情况,还大大的增加了工作量,减少了系统的可维护性。

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



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

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

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

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

代码的实现

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>publicclassLogManager<T>whereT:new()
{#regionConstructor///<summary>
///日志管理构造函数///</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{thrownewArgumentNullException("日志设置为空!");
}
}///<summary>//////日志管理构造函数///</summary>
///</summary>
///<paramname="tableName">表名</param>
///<paramname="businessName">业务名称</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{thrownewArgumentNullException("日志设置为空!");
}
}#endregion

#regionPropertiesprivateintlogID;privatestringtableName;privatestringbusinessName;privatestringprimaryKey;privatestringurlTemplate;privatestringdeleteScriptTemplate;privatestringupdateScriptTemplate;///<summary>
///日志设置实体列表///</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>
///日志设置明细///</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获取日志设置明细///</summary>
///<paramname="logId">日志设置编号</param>
///<returns></returns>privateList<Model.Sys.LogSettingDetail>GetLogSettingDetails(intlogId)
{if(logId==0)thrownewArgumentNullException("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来获取日志设置对象///</summary>
///<paramname="tableName"></param>
///<paramname="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;
}returnnull;
}privateModel.Sys.LogSettingGetLogSetting(stringtableName)
{foreach(Model.Sys.LogSettingvarinLogSettingList)
{if(var.TableName.Equals(tableName,StringComparison.InvariantCultureIgnoreCase))returnvar;
}returnnull;
}///<summary>
///比较两个实体,然后返回实体中每个属性值不同的内容///</summary>
///<paramname="oldObj"></param>
///<paramname="newObj"></param>
///<returns></returns>publicstringCompare(ToldObj,TnewObj)
{TypeobjTye=typeof(T);StringBuildersbResult=newStringBuilder();stringtableHeader="<tableclass=/"GridView/"cellspacing=/"0/"rules=/"all/"border=/"1/"id=/"gv/"style=/"border-collapse:collapse;/">";
tableHeader+="<tr><thscope=/"col/">序号</th><thscope=/"col/">字段</th><thscope=/"col/">名称</th><thscope=/"col/">旧值</th><thscope=/"col/">新值</th></tr>";stringtableRow="<trclass='{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>");#regionAddLogRecordif(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);

}#endregion

returntableHeader+sbResult.ToString();

}///<summary>
///删除实体操作,这里并不是真的删除该实体,而是将删除的操作记录在日志中///</summary>
///<paramname="obj"></param>
///<returns></returns>publicstringDelete(Tobj)
{TypeobjTye=typeof(T);StringBuildersbResult=newStringBuilder();stringtableHeader="<tableclass=/"GridView/"cellspacing=/"0/"rules=/"all/"border=/"1/"id=/"gv/"style=/"border-collapse:collapse;/">";
tableHeader+="<tr><thscope=/"col/">序号</th><thscope=/"col/">字段</th><thscope=/"col/">名称</th><thscope=/"col/">值</th></tr>";stringtableRow="<trclass='{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>");#regionAddLogRecord

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);#endregion
returnstring.Empty;
}///<summary>
///添加实体,将添加的操作记录在日志中///</summary>
///<paramname="obj"></param>
///<returns></returns>publicstringAdd(Tobj)
{TypeobjTye=typeof(T);StringBuildersbResult=newStringBuilder();stringtableHeader="<tableclass=/"GridView/"cellspacing=/"0/"rules=/"all/"border=/"1/"id=/"gv/"style=/"border-collapse:collapse;/">";
tableHeader+="<tr><thscope=/"col/">序号</th><thscope=/"col/">字段</th><thscope=/"col/">名称</th><thscope=/"col/">值</th></tr>";stringtableRow="<trclass='{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>");#regionAddLogRecord

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);#endregion
returnstring.Empty;
}///<summary>
///复制一个对象///</summary>
///<paramname="obj"></param>
///<returns></returns>publicTClone(Tobj)
{TypeobjTye=typeof(T);
Tmodel=newT();PropertyInfo[]properties=objTye.GetProperties();foreach(PropertyInfopropertyinproperties)
{if(!property.IsSpecialName)
{objecto=property.GetValue(obj,null);
property.SetValue(model,o,null);
}

}returnmodel;
}privateboolIsEqual(TypedataType,objectoldObj,objectnewObj)
{if(oldObj==null&&newObj==null)returntrue;if(dataType==typeof(int))
{return(int)oldObj==(int)newObj;
}elseif(dataType==typeof(decimal))
{return(decimal)oldObj==(decimal)newObj;
}elseif(dataType==typeof(double))
{return(double)oldObj==(double)newObj;
}elseif(dataType==typeof(Guid))
{return(Guid)oldObj==(Guid)newObj;
}elseif(dataType==typeof(DateTime))
{return(DateTime)oldObj==(DateTime)newObj;
}else
returnoldObj.Equals(newObj);

}#regionScript.Excute//publicintDeleteBusRecode(stringprimaryKeyValue)
//{
//if(string.IsNullOrEmpty(tableName))
//thrownewArgumentException("tableName为空");
//if(string.IsNullOrEmpty(primaryKey))
//thrownewArgumentException("primaryKey为空");
//if(string.IsNullOrEmpty(deleteScriptTemplate))
//thrownewArgumentException("deleteScriptTemplate为空");

//stringstrSql=string.Format(deleteScriptTemplate,primaryKeyValue);

//Databasedb=DatabaseFactory.CreateDatabase();
//return0;

//}#endregion

#endregion}publicenumOperationType{
Select=0,
Add=1,
Update=2,
Delete=3
}



使用的场景

Model文件:

publicclassEmployeeModel

{publicintID{get;set;}publicstringName{get;set;}

…

}

下面介绍如何将系统操作日志集成到你的业务系统中

添加操作:

EmployeeBllbll=newEmployeeBll();

EmployeeModelmodel=newEmployeeModel();

/*model实体经过漫长的赋值后…*/

bll.Add(model);//添加实体

//添加系统操作记录

//日志LogManager<EmployeeModel>log=newLogManager<EmployeeModel>();


log.Add(model);


更新操作:

EmployeeBllbll=newEmployeeBll();

EmployeeModelmodel=bll.GetModel(employeeID);

LogManager<EmployeeModel>log=newLogManager<EmployeeModel>();

EmployeeModelmodelOld=log.Clone(model);//克隆EmployeeModel实体对象,这个主要是在系统操作日志记录时使用的


/*model实体又经过漫长的赋值后…*/

bll.Update(model);//更新实体

//将更新的内容写入系统操作日志中

log.Compare(modelOld,model);//原来的实体和赋值后的实体对比,并将更新的内容写入系统操作日志中


删除操作:

在GridView的RowDeleting事件中获取要删除的实体

EmployeeBllbll=newEmployeeBll();

EmployeeModelmodel=bll.GetModel(employeeID);

bll.Delete(employeeID);

LogManager<EmployeeModel>log=newLogManager<EmployeeModel>();
log.Delete(model);//实体的内容记录到日志中



.csharpcode,.csharpcodepre{font-size:small;color:black;font-family:consolas,"CourierNew",courier,monospace;background-color:#ffffff;/*white-space:pre;*/}.csharpcodepre{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、可扩展性较差
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: