Dapper扩展SQL跟踪及全局缓存通知

具体原因就不说了,目前项目的构成有两部分,一部分是是基于框架开发的,另一部是由于早期业务是采用自定义开发模式,虽然数据访问层都是基于Dapper,

但要做全局sql跟踪及缓存通知,调整代码还是有些麻烦,最后还是动手简单扩展一个Dapper的源码,从底层来进行处理。

调整Dapper源码中有一个很重要的类:CommandDefinition.cs

1、执行SQL前拦截事件

 

2、执行SQL后拦截事件(后失败会不触发)

3、SQLMapper.cs增加一行代码(此处应该是作者漏掉了,没有细读)

 

 

4、附上SqlMapperTrace.cs源码

  1 using System;
  2 using System.Collections.Generic;
  3 using System.Linq;
  4 using System.Text;
  5 using System.Threading.Tasks;
  6 
  7 namespace Dapper
  8 {
  9     /// <summary>
 10     /// Sql执行拦截事件
 11     /// </summary>
 12     /// <param name="traceInfo"></param>
 13     public delegate void BeforeCommandExecute(TraceInfo traceInfo);
 14     /// <summary>
 15     /// SQL运行成功后拦截事件
 16     /// </summary>
 17     /// <param name="traceInfo"></param>
 18     public delegate void AfterCommandExecute(TraceInfo traceInfo);
 19     /// <summary>
 20     /// DapperSQL执行跟踪
 21     /// </summary>
 22     public class SqlMapperTrace
 23     {
 24         static BeforeCommandExecute BeforeSqlCommand = null;
 25         static AfterCommandExecute AfterSqlCommand = null;
 26         /// <summary>
 27         /// 设置DapperSql执行拦截事件
 28         /// </summary>
 29         /// <param name="beforeExecuteTrace">执行前事件</param>
 30         /// <param name="afterExecuteTrace">执行后事件</param>
 31         public static void SetMapperTrace(BeforeCommandExecute beforeExecuteTrace, AfterCommandExecute afterExecuteTrace)
 32         {
 33             if (null != BeforeSqlCommand)
 34                 return;
 35             BeforeSqlCommand = beforeExecuteTrace;
 36             AfterSqlCommand = afterExecuteTrace;
 37 
 38         }
 39 
 40       /// <summary>
 41       /// 执行SQL运行前拦截事件
 42       /// </summary>
 43       /// <param name="traceInfo"></param>
 44         internal static void ShellBeforeCommandExecute(TraceInfo traceInfo)
 45         {
 46             if (null != BeforeSqlCommand)
 47                 BeforeSqlCommand( traceInfo);
 48         }
 49 
 50         /// <summary>
 51         /// 执行SQL运行成功后拦截事件,若SQL执行失败,则此方法不会触发
 52         /// </summary>
 53         /// <param name="traceInfo"></param>
 54         public static void ShellAfterCommandExecute(TraceInfo traceInfo)
 55         {
 56             if (null != AfterSqlCommand)
 57                 AfterSqlCommand(traceInfo);
 58         }
 59     }
 60 
 61     /// <summary>
 62     /// Sql执行状态
 63     /// </summary>
 64     public enum SqlState
 65     {
 66         /// <summary>
 67         /// 执行中
 68         /// </summary>
 69         Start,
 70         /// <summary>
 71         /// 完成 
 72         /// </summary>
 73         End,
 74         /// <summary>
 75         /// 失败
 76         /// </summary>
 77         Error
 78     }
 79 
 80     /// <summary>
 81     /// 跟踪信息
 82     /// </summary>
 83     public class TraceInfo
 84     {
 85         /// <summary>
 86         /// 操作识别Key,用用跟踪同一SQL是否执行成功
 87         /// </summary>
 88         public string Token { get; set; }
 89         /// <summary>
 90         /// SQL语句
 91         /// </summary>
 92         public String CommandText { get; set; }
 93         /// <summary>
 94         /// sql参数
 95         /// </summary>
 96         public object SqlParams { get; set; }
 97 
 98         /// <summary>
 99         /// 是否正在启动
100         /// </summary>
101         public SqlState IsStart { get; set; }
102         /// <summary>
103         /// 执行时间,性能统计,自己可根据两次时间差去实现
104         /// </summary>
105         public DateTime ExecuteTime { get; set; }
106 
107         /// <summary>
108         /// 是否执行数据库成功,主要针对增删改操作
109         /// </summary>
110         public bool IsDbSucc { get; set; }
111 
112         /// <summary>
113         /// 提示信息
114         /// </summary>
115         public string Message { get; set; }
116     }
117 
118 }

 

5、调用拦截注入

   

 

 

6、特别说明:

     由于Dapper中数据库执行出错后,不再执行 SQL执行完成事件,即(第2步的OnCompleted事件),所以在框架里我再处理了一层

这样就简单实现了SQL语句跟踪,下一步会继续 日志写入及从SQL语句中分离出 表名及执行动作,与Redis配合做缓存通知处理。

posted @ 2017-10-25 08:53  xspots-Will  阅读(1412)  评论(0编辑  收藏  举报