C# Dapper缓存问题?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C# Dapper缓存问题?相关的知识,希望对你有一定的参考价值。
大家好,我在项目中遇到了问题,就是 有一个存储过程,获取分配的ID的,调取一次会自动增加。当我使用dapper调取这个存储过程的时候 会有缓存现象。如图当我使用SQL语句就不会出现这个问题,是dapper的缓存问题吗,如何设置不缓存?
参考技术A 第一个问题是为什么你的存储过程不直接处理好参数,要另外定义一个带变量的sql语句来执行第二个,上面的base是什么,ExecuteSp方法是自己写的还是Dapper的(我觉得一个流行类库不应该取这么丑的方法名)?
如果单纯说比如Dapper的Query方法
通常可以用db.Query(sql)
也有重载 Query<T>(this IDbConnection cnn, CommandDefinition command)
var cmdDef = new CommandDefinition("select ... blah ...", new a, b , commandType: CommandType.Text, flags: CommandFlags.NoCache);
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 string Message { get; set; } 111 } 112 113 }
5、调用拦截注入
6、特别说明:
由于Dapper中数据库执行出错后,不再执行 SQL执行完成事件,即(第2步的OnCompleted事件),所以在框架里我再处理了一层
这样就简单实现了SQL语句跟踪,下一步会继续 日志写入及从SQL语句中分离出 表名及执行动作,与Redis配合做缓存通知处理。
以上是关于C# Dapper缓存问题?的主要内容,如果未能解决你的问题,请参考以下文章