C# 获取EF savechanges() 的增删改的SQL语句
如何获取SaveChanges()的SQL语句。
目的: 在涉及到数据库的项目中,增删改是非常关键的操作,最好是详细的记录到日志中,而详细 莫过于直接将SQL语句记录到数据库日志中了。
像下面这个方法里面的就相当于UPDATE了,属于关键性操作
private void UpdatePredictionState(List<Guid> ids) { foreach (var id in ids) { var prediction = _context.PredictionInfos.Find(id); prediction.State = 2; _context.SaveChanges(); } }
那么如何获取_context.SaveChanges()的SQL语句呢?
第一步:展示SQL语句
EF6 有关于日志的一个方法来专门获取数据库事务的语句(我也是因为这个才知道什么叫数据库的事务,之前学过没有实践也就忘了-----(事务:简单来说是数据库操作中的最小单位,可以看做是一次的增删改查,不知道这么理解对不对,不对的话 请大神们指教))context.Database.log 这个我在网上查了好久,因为是萌新 不会用!!!!然后我就请教大神了(手动滑稽)。
具体用法如下:
public DownholeToolsTypeController(LoggingJobContext context):base("下井仪器类型") { _context = context; _context.Database.Log = s => { Console.WriteLine(s); }; }
将这个写在控制器的构造器里面,每当运行方法时会先运行构造器然后运行指定的方法,这样运行方法时,就会监听有没有数据库的事务,有的话就会将事务输出到控制台上,运行结果如下:
这样会把所有的数据库事务都写出来,既然能获取出来了,那么写入数据库就不是很难了。
但是select 不是我们所说的关键性记录啊,我们只要增!删!改!!!
不难,但是作为萌新,我用了最笨的办法获取到了我需要的数据
_loggingJobContext.Database.Log = s => { string sqlstr=""; if (sw == 1) { sqlstr += s; } if (s.Length > 12) { if (s.Substring(0, 6) == "INSERT" || s.Substring(0, 6) == "UPDATE" || s.Substring(0, 6) == "DELETE") { sqlstr += s; sw = 1; } if (s.Substring(0, 13).Contains("Completed") && s.Substring(s.Length - 3, 1) == "1") { sw = 0; } } _sqlStrBuilder.AppendLine(sqlstr);
当然 前面的变量:StringBuilder _sqlStrBuilder=new StringBuilder(); int sw = 0;必不可少的。
经过研究发现,打开关闭连接对我们是没有用的,最有用的其实就是sql语句以数据变量 还有完成结果
这样就可以只记录增删改的操作记录了;
但是,每一个控制器都要这么写,麻烦,于是我想简单一些,叫代码重用,咋弄呢,我写了个类,想引用这个类,发现不行,于是请教大神,大神就教我做人了(教我知道什么是父类了,其实知道什么是父类,但是写的少,压根没有往父类上想)
第二步:
代码重用问题,由于日志问题,大神们已经写好了父类方法了,但是基本上并没有SQL语句的方法,于是我把我上面的代码放到了父类的构造器里面
并在下图2里面添加了 有关url的语句 这样 日志就会记载访问的是哪个url和 sql语句是啥 都有了。
上这个图的目的 也是为了记录一下,并且让自己记住,OnActionExecuting和OnActionExecuted的执行先后顺序,先执行子类的构造器 然后执行父类的构造器,然后执行OnActionExecuting方法再执行子类的方法,最后执行OnActionExecuted方法。所以最后记录的方法写在OnActionExecuted里面是表示着 最终的记录。
大神最后,给我说了一些知识点,说是要检查的:知识点我会放在下面,然后如果学习有心得,我会继续写博客的。
大神说上述问题有关的知识点:
实例化子类对象时,子类、父类、父父类构造器的执行顺序
调用父类构造器的意义
用父类或抽象类类型的变量编程的意义
虚函数
Controller对象的生命周期