博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
EntityFramework的多种记录日志方式,记录错误并分析执行时间过长原因(系列4)
阅读量:5334 次
发布时间:2019-06-15

本文共 4393 字,大约阅读时间需要 14 分钟。

今天我们来聊聊EF的日志记录.

一个好的数据库操作记录不仅仅可以帮你记录用户的操作,

更应该可以帮助你获得效率低下的语句来帮你提高运行效率

废话不多说,我们开始

 

环境和相关技术
本文采用的环境与技术

系统:WIN7

数据库:SQL Server2008

相关技术:MVC5     EF6.0+

简单的记录

一、修改配置文件

我们先来看看最简化的EF日志记录,任何代码都不用改,在你的配置文件中加入如下配置即可自动记录:

在你的EntityFramework节点下加入如下配置即可(这里需要注意的是第一个参数是你日志的输出地址):

我们到对应的地址下就能找相关的日志文件了如下:

 

二、简单封装:

编写一个自己的DBContext的基类如下:

public class DataBaseContext
: DbContext where T:class,new(){ //重写SaveChanges方法 public override int SaveChanges() { string sql = ""; //记录实体操作日志 this.Database.Log = (a) => { sql += a; }; //这里的sql就是操作日志了,想记哪就记哪吧.这里我就不实现了. return base.SaveChanges(); }}

 

 

 

 

通过低级监听接口来进行监听

如果你只是想单纯的记录,上面两种方式应该就能满足你了.

我们记录的目的其实最重要的还是在于分析性能 下面就开始我们的重头戏.

采用IDbCommandInterceptor接口进行EF的监听

首先我们来看看这个接口里面到底有些什么:

写过ADO.NET的人 应该对这些单词很熟悉了吧.(因为EF最终访问数据库的方式还是用的ADO.NET)

注意:每个执行都有ed(执行完成后的监听)和ing(执行时的监听)

下面我们来一步一步实现这个接口

首先定义一个类(名字你随意):

//名字可以随意,但是肯定要继承我们的监听接口 - - ,    public class DatabaseLogger : IDbCommandInterceptor{}

然后我们继续,

定义一个静态只读的ConcurrentDictionary作为我们的记录仓储,考虑到数据访问时多线程的情况很常见,所以我们采用线程安全的ConcurrentDictionary

代码如下:

public class DatabaseLogger : IDbCommandInterceptor {        static readonly ConcurrentDictionary
MStartTime = new ConcurrentDictionary
(); }

接下来,我们来实现我们所需要的两个方法 一个为onStart来记录SQL语句执行开始的时间

如下:

//记录开始执行时的时间 private static void OnStart(DbCommand command) {            MStartTime.TryAdd(command, DateTime.Now); }

然后实现我们的log方法来记录相关的SQL语句和错误信息

private static void Log
(DbCommand command, DbCommandInterceptionContext
interceptionContext) { DateTime startTime; TimeSpan duration; //得到此command的开始时间 MStartTime.TryRemove(command, out startTime); if (startTime != default(DateTime)) { duration = DateTime.Now - startTime; } else duration = TimeSpan.Zero; var parameters = new StringBuilder(); //循环获取执行语句的参数值 foreach (DbParameter param in command.Parameters) { parameters.AppendLine(param.ParameterName + " " + param.DbType + " = " + param.Value); } //判断语句是否执行时间超过1秒或是否有错 if (duration.TotalSeconds > 1 || interceptionContext.Exception!=null) { //这里编写记录执行超长时间SQL语句和错误信息的代码 } else { //这里编写你自己记录普通SQL语句的代码 } }

既然我们已经得到了想要的东西,那具体的记录方式,各位仁者见仁 智者见智 就随意了,所以我这就不写了.

然后接着,我们要实现这个接口的6个方法,如下:

public void NonQueryExecuted(DbCommand command, DbCommandInterceptionContext
interceptionContext) { Log(command, interceptionContext); } public void NonQueryExecuting(DbCommand command, DbCommandInterceptionContext
interceptionContext) { OnStart(command); } public void ReaderExecuted(DbCommand command, DbCommandInterceptionContext
interceptionContext) { Log(command, interceptionContext); } public void ReaderExecuting(DbCommand command, DbCommandInterceptionContext
interceptionContext) { OnStart(command); } public void ScalarExecuted(DbCommand command, DbCommandInterceptionContext
interceptionContext) { Log(command, interceptionContext); } public void ScalarExecuting(DbCommand command, DbCommandInterceptionContext interceptionContext) { OnStart(command); }

其实很简单,就是所有的ing执行我们之前写的OnStart方法,所有的ed执行我们的log方法即可.

接下来,我们需要注入这个接口:

这里我的Demo用的MVC所以我就在 Application_Start()中直接注入了,如下:

protected void Application_Start(){          //注入自己写的监听            DbInterception.Add(new MiniProfiler_EFModel.DatabaseLogger());}

这样我们就完成了整个监听的过程了~

实现效果如下:

我们得到了执行的秒数

得到了执行的SQL语句:

得到了SQL语句所对应的参数:

大功告成!

写在最后

这里我只是帮各位通过监听来获取到相关的信息,具体如何优化,应该用什么东西进行记录,我就不过多的赘述,这是属于仁者见仁智者见智的东西,不过有兴趣的可以通过博客加我QQ进行讨论.欢迎.

作者:顾振印 出处:http://www.cnblogs.com/GuZhenYin/ 如果您觉得阅读本文对您有帮助,请点一下“推荐”按钮,您的“推荐”将是我最大的写作动力!本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面

转载于:https://www.cnblogs.com/shiningrise/p/5585149.html

你可能感兴趣的文章
ArcGIS多面体(multipatch)解析——引
查看>>
css3渐变画斜线 demo
查看>>
JS性能DOM优化
查看>>
设计模式 单例模式 使用模板及智能指针
查看>>
c#的const可以用于引用类型吗
查看>>
手动实现二值化
查看>>
What Linux bind mounts are really doing
查看>>
linux top命令详解
查看>>
博弈论小结
查看>>
模拟Post登陆带验证码的网站
查看>>
NYOJ458 - 小光棍数
查看>>
java中常用方法
查看>>
【Programming Clip】06、07年清华计算机考研上机试题解答(个别测试用例无法通过)...
查看>>
canvas动画
查看>>
4,7周围玩家
查看>>
关于webpack升级过后不能打包的问题;
查看>>
vue - 生命周期
查看>>
SQL Server用户权限详解
查看>>
Python正则表达式
查看>>
Linux进程间通信--命名管道
查看>>