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缓存问题?的主要内容,如果未能解决你的问题,请参考以下文章

dapper 缓存的“信息”到底是啥?

dapper C#的Iconvertible问题

使用 Dapper (C#) 调用 PostgreSQL 存储过程

如何使用 Dapper.NET 将 C# 列表插入数据库

选择语句:列名无效,在 C# 中使用 Dapper

dapper.net,如何刷新 ConcurrentDictionary?