Winform开发框架之权限管理系统改进的经验总结(4)-一行_第1页
Winform开发框架之权限管理系统改进的经验总结(4)-一行_第2页
Winform开发框架之权限管理系统改进的经验总结(4)-一行_第3页
Winform开发框架之权限管理系统改进的经验总结(4)-一行_第4页
Winform开发框架之权限管理系统改进的经验总结(4)-一行_第5页
已阅读5页,还剩7页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、Winform开发框架之权限管理系统改进的经验总结(4)-一行代码实现表操作日志记录在前面介绍了几篇关于我的权限系统改进的一些经验总结,本篇继续这一系列主体,介绍如何一行代码实现重要表的操作日志记录。我们知道,在很多业务系统里面,数据是很敏感的,特别对于一些增加、修改、删除等关键的操作,如果能在框架层面的支持基础上,以最少的代码实现重要表的日志记录,那么是一件非常值得庆贺的事情,也能够为我们客户的数据提供重要的日志跟踪,甚至是数据恢复的参考。1、数据访问层的对象继承关系首先,为了减少重复代码的编写,合理的继承关系是必要的,我们需要在数据访问层上建立合理的继承关系,如下是我的Winform开发框

2、架的继承关系。每个数据访问对象(如ItemDetail数据访问对象)都继承一个抽象基类AbstractBaseDAL和一个IBaseDAL基类接口,同时它也有自己特殊的业务接口,如IItemDetail,关系如下所示。有了上面的继承关系,我们就可以把常规的数据库重要操作(增删改)放到一个高一级的层次上去解决这个问题,而不需要在每个数据访问层的业务类来实现。2、操作日志记录事件的定义和使用为了更好实现数据操作日志的记录,我们以事件方式来触发操作日志的记录,事件的具体记录实现,可以交给外部来记录处理。如果事件被外部赋值了,那么就可以在底层触发这个事件记录,记录事件的定义代码在抽象基类进行定义,如下

3、所示。 / 定义一个记录操作日志的事件处理 / </summary> / <param name="userId">操作的用户ID</param> / <param name="tableName">操作表名称</param> / <param name="operationType">操作类型:增加、修改、删除</param> / <param name="note">操作的详细记录信息</param> /

4、 <returns></returns> public delegate bool OperationLogEventHandler(string userId, string tableName, string operationType, string note, DbTransaction trans = null); / <summary> / 数据访问层的超级基类,所有数据库的数据访问基类都继承自这个超级基类,包括Oracle、SqlServer、Sqlite、MySql、Access等 / </summary> public abst

5、ract class AbstractBaseDAL<T> where T : BaseEntity, new() #region 构造函数 protected string dbConfigName = "" /数据库配置名称 protected string parameterPrefix = ""/数据库参数化访问的占位符 protected string safeFieldFormat = "0"/防止和保留字、关键字同名的字段格式,如value protected string tableName;/需要初始化的

6、对象表名 protected string primaryKey;/数据库的主键字段名 protected string sortField;/排序字段 protected bool isDescending = true;/是否为降序 protected string selectedFields = " * "/选择的字段,默认为所有(*) public event OperationLogEventHandler OnOperationLog;/定义一个操作记录的事件处理.以上是抽象基类AbstractBaseDAL的部分代码,上面代码定义了一个操作记录的委托和事件对

7、象来处理操作日志的记录,通过委托的定义,我们可以规定具体的事件接口定义,并在抽象基类的底层构造这些参数的数值,传递给外部的对象进行处理。那么我们是如何在底层操作构造这些信息的呢?其实就是在相应的重要操作接口函数上调用这个定义的事件。我们可以在抽象基类的插入、修改、删除等接口上调用事件进行处理即可,为了更好处理相关数据的构造逻辑,我们把调用OnOperationLog的事件封装到一个单独的函数里面进行处理,如下所示是底层更新操作的代码,通过增加一个OperationLogOfUpdate来实现数据日志的事件处理。 / <summary> / 更新对象属性到数据库中 / </su

8、mmary> / <param name="obj">指定的对象</param> / <param name="primaryKeyValue">主键的值</param> / <param name="trans">事务对象</param> / <returns>执行成功返回<c>true</c>,否则为<c>false</c>。</returns> public virtual boo

9、l 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); 然后我们在具体的事件处理封装函

10、数OnOperationLog的里面添加处理逻辑即可,一般事件的标准处理为如下代码。 / <summary> / 修改操作的日志记录 / </summary> / <param name="id">记录ID</param> / <param name="obj">数据对象</param> / <param name="trans">事务对象</param> protected virtual void OperationLogOfUpdat

11、e(T obj, object id, DbTransaction trans = null) if (OnOperationLog != null) ./构造相关参数 OnOperationLog(userId, this.tableName, operationType, note, trans); 我们知道,一般操作日志都会记录是谁进行操作的,然后把它写到日志里面,并把操作的内容可读化即可,那么在更新的时候,我们如何知道是谁操作的对象呢?因为我们没有传递具体的用户ID等标识的啊。这个问题挺头痛,如果增加多一个参数,那么就得修改很多相关的调用逻辑,这个明显不太符合我们简约的风格,因此最好另

12、寻其他方式来实现这个人员身份记录的问题。我们知道,一般插入、更新操作,都是带一个操作对象的,这个操作对象是一个实体类,基类是BaseEntity,那么我们可以在它的身上定义多一个属性,这个属性不参数数据的保存,只是作为参数的传递和识别而已,实体类基类的代码如下所示。 / <summary> / 框架实体类的基类 / </summary> DataContract public class BaseEntity private string m_CurrentLoginUserId; / <summary> / 当前登录用户ID。该字段不保存到数据表中,只用于

13、记录用户的操作日志。 / </summary> DataMember public string CurrentLoginUserId get return m_CurrentLoginUserId; set m_CurrentLoginUserId = value; 有了这个信息,我们就可以在刚才的事件处理逻辑上进行获取用户的ID操作了。string userId = obj.CurrentLoginUserId;下一个问题是,如何把操作的信息可读化,我们知道,一般操作只是对部分字段进行修改,那么我们一般也不需要把所有的字段信息都弄出来显示,只需要显示那些修改的即可。为了实现这个

14、数据的差异化显示,我们需要在更新操作之前进行获取数据库的对象信息,然后和将要进行更新的对象进行对比,把差异的信息作为备注信息记录下来即可,具体逻辑如下所示。 / <summary> / 修改操作的日志记录 / </summary> / <param name="id">记录ID</param> / <param name="obj">数据对象</param> / <param name="trans">事务对象</param> protec

15、ted 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 = GetColumn

16、NameAlias(); T objInDb = FindByID(id, trans); if (objInDb != null) Hashtable dbrecordField = GetHashByEntity(objInDb);/把数据库里的实体对象数据转换为哈希表 StringBuilder sb = new StringBuilder(); foreach (string field in recordField.Keys) string newValue = recordFieldfield.ToString(); string oldValue = dbrecordFieldf

17、ield.ToString(); if (newValue != oldValue)/只记录变化的内容 string columnAlias = "" bool result = dictColumnNameAlias.TryGetValue(field, out columnAlias); if (result && !string.IsNullOrEmpty(columnAlias) columnAlias = string.Format("(0)", columnAlias);/字段中文名称前,增加一个括号显示,方便区分显示 sb.

18、AppendLine(string.Format("01:", field, columnAlias); sb.AppendLine(string.Format("t 0 -> 1", dbrecordFieldfield, recordFieldfield); sb.AppendLine(); sb.AppendLine(); string note = sb.ToString(); OnOperationLog(userId, this.tableName, operationType, note, trans); 上面是更新操作的日志记录处理

19、,其他的插入、删除等操作类似这样的操作方式,再次不在赘述。3、业务层对操作日志信息的处理上面的代码只是实现了对底层操作的信息记录并传递给操作日志的记录事件,并没有知道上层是如何处理事件信息的记录的,这个问题留给上层去处理。为了实现这个信息的记录,我们在权限系统里面增加一个单独的数据库表如T_ACL_OperationLog表用来专门记录这些信息的。上层的处理逻辑是获取用户ID的登陆信息,包括用户名、用户IP地址、Mac地址信息等,这些信息一旦用户登陆到系统就会发生了,所以可以方便获取到,然后就是把这些信息作为一个数据库记录写入数据库表即可。 OperationLogInfo info = ne

20、w 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.Log

21、inName = 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);因为这些记录

22、的操作都是一样的,为了更方便,我们把这些逻辑封装在一个静态的方法里面,然后所有需要记录操作日志的,在业务对象里面增加一行代码,就可以轻松实现日志记录了,具体代码如下所示。 / <summary> / 部门机构信息 / </summary> public class OU : BaseBLL<OUInfo> private IOU ouDal; / <summary> / 构造函数 / </summary> 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; 这样数据访问类

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

最新文档

评论

0/150

提交评论