[转]EntityFramework的多种记录日志方式,记录错误并分析执行时间过长原因(系列4)…[通俗易懂]

[转]EntityFramework的多种记录日志方式,记录错误并分析执行时间过长原因(系列4)…

大家好,又见面了,我是全栈君。

本文转自:https://www.cnblogs.com/GuZhenYin/p/5556732.html

Entity Framework 延伸系列目录

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

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

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

废话不多说,我们开始

 

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

系统:WIN7

数据库:SQL Server2008

相关技术:MVC5     EF6.0+

简单的记录

一、修改配置文件

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

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

复制代码
<interceptors>
      <interceptor type="System.Data.Entity.Infrastructure.Interception.DatabaseLogger, EntityFramework">
        <parameters>
          <parameter value="D:\ttt\log.txt" />
          <parameter value="true" type="System.Boolean" />
        </parameters>
      </interceptor>
    </interceptors>
复制代码

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

[转]EntityFramework的多种记录日志方式,记录错误并分析执行时间过长原因(系列4)...[通俗易懂]

 

二、简单封装:

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

复制代码
 public class DataBaseContext<T> : DbContext where T:class,new()
{
    //重写SaveChanges方法
     public override int SaveChanges()
     {
              string sql = "";
                //记录实体操作日志
                    this.Database.Log = (a) =>
                    {

                        sql += a;
                    };
            //这里的sql就是操作日志了,想记哪就记哪吧.这里我就不实现了.
            return base.SaveChanges();
      }
}
复制代码

 

 

 

 

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

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

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

采用IDbCommandInterceptor接口进行EF的监听

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

[转]EntityFramework的多种记录日志方式,记录错误并分析执行时间过长原因(系列4)...[通俗易懂]

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

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

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

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

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

然后我们继续,

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

代码如下:

复制代码
 public class DatabaseLogger : IDbCommandInterceptor
 {

        static readonly ConcurrentDictionary<DbCommand, DateTime> MStartTime = new ConcurrentDictionary<DbCommand, DateTime>();

 }
复制代码

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

如下:

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

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

复制代码
        private static void Log<T>(DbCommand command, DbCommandInterceptionContext<T> 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<int> interceptionContext)
        {
            Log(command, interceptionContext);
        }

        public void NonQueryExecuting(DbCommand command, DbCommandInterceptionContext<int> interceptionContext)
        {
            OnStart(command);
        }

        public void ReaderExecuted(DbCommand command, DbCommandInterceptionContext<DbDataReader> interceptionContext)
        {

            Log(command, interceptionContext);
        }

        public void ReaderExecuting(DbCommand command, DbCommandInterceptionContext<DbDataReader> interceptionContext)
        {
            OnStart(command);
        }
        public void ScalarExecuted(DbCommand command, DbCommandInterceptionContext<object> interceptionContext)
        {
            Log(command, interceptionContext);
        }

        public void ScalarExecuting(DbCommand command, DbCommandInterceptionContext<object> interceptionContext)
        {

            OnStart(command);
        }
复制代码

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

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

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

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

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

实现效果如下:

我们得到了执行的秒数

[转]EntityFramework的多种记录日志方式,记录错误并分析执行时间过长原因(系列4)...[通俗易懂]

得到了执行的SQL语句:

[转]EntityFramework的多种记录日志方式,记录错误并分析执行时间过长原因(系列4)...[通俗易懂]

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

[转]EntityFramework的多种记录日志方式,记录错误并分析执行时间过长原因(系列4)...[通俗易懂]

大功告成!

写在最后

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

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

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/107814.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • pycharm界面怎么调成中文版(pycharm怎么破解)

    文章目录汉化方法官方汉化与第三方对比Java的idea在更新2020.1时就更新了官方汉化,当时Pycharm还没用出现汉化,但这两天提示我更新2020.1.1的时候,我发现pycharm也出现了官方汉化,在此建议你要是想用官方汉化,先把你的pycharm升级为最新版本。汉化方法打开pycharm左上角的file(文件)>选择settings(设置)>打开plugins(插件)>搜索chinese(中文插件),下载好后重启pycharm。官方汉化与第三方对比这里使用

    2022年4月10日
    144
  • 一文读懂Spring 循环依赖,写得太好了!(建议收藏)

    点击上方“全栈程序员社区”,星标公众号 重磅干货,第一时间送达 转自:Vt 链接:juejin.im/post/5e927e27f265da47c8012ed9 前言 Spring…

    2021年6月23日
    90
  • 双非本科22届暑期实习,成功拿到B站、阿里实习offer[通俗易懂]

    双非本科22届暑期实习,成功拿到B站、阿里实习offer[通俗易懂]拼一把不一定成功,但是不试试看肯定没有结果!1.前言想写这篇文章很久了,也有粉丝留言、私信问我打卡系列怎么断更了这么多天(狗头保命),首先给大家解释一下最近为什么“失踪了”?由于近两周要入职,找租房,整理微信公众号,所以没多少时间写博客,今天难得闲下来,做一篇近期总结给大家。关于交流群:有粉丝私信,建议创建一个学习群,大家互相分享校招经验,学习心得(我因为怕管理群太麻烦,而一拖再拖,不过也好歹建群了),大家可以通过我的博客首页关注一波公众号:兴趣使然的草帽路飞去获取交流群和内推群群.

    2022年5月21日
    51
  • [Odoo] Odoo Postgres 遇到 5432 的问题解决办法[通俗易懂]

    [Odoo] Odoo Postgres 遇到 5432 的问题解决办法[通俗易懂]把odoo.conf文件还原到最原始状态然后把odoo.conf中的路径替换为自己的路径重启Odoo服务

    2022年6月19日
    26
  • 视频编解码优化的几个概念[通俗易懂]

    视频编解码优化的几个概念[通俗易懂]视频编解码1.neon2.gpu加速3.汇编neon在移动平台上进行一些复杂算法的开发,一般需要用到指令集来进行加速。目前在移动上使用最多的是ARM芯片。ARM是微处理器行业的一家知名企业,其芯片结构有:armv5、armv6、armv7和armv8系列。芯片类型有:arm7、arm9、arm11、cortex系列。指令集有:armv5、armv6和neon指令。关于ARM到知识参考:ht

    2022年7月15日
    24
  • ingress的用法与原理[通俗易懂]

    ingress的用法与原理[通俗易懂]前言我们知道真正提供服务的是后端的pod,但是为了负载均衡,为了使用域名,为了….,service诞生了,再后来ingress诞生了,那么为什么需要有Ingress呢?先看看官网怎么说的:In

    2022年7月1日
    62

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号