EntityFramework的多种记录日志方式,记录错误并分析执行时间过长原因(系列4)
今天我们来聊聊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>
我们到对应的地址下就能找相关的日志文件了如下:
二、简单封装:
编写一个自己的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的监听
首先我们来看看这个接口里面到底有些什么:
写过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 > || 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());
}
这样我们就完成了整个监听的过程了~
实现效果如下:
我们得到了执行的秒数
得到了执行的SQL语句:
得到了SQL语句所对应的参数:
大功告成!
这里我只是帮各位通过监听来获取到相关的信息,具体如何优化,应该用什么东西进行记录,我就不过多的赘述,这是属于仁者见仁智者见智的东西,不过有兴趣的可以通过博客加我QQ进行讨论.欢迎.
EntityFramework的多种记录日志方式,记录错误并分析执行时间过长原因(系列4)的更多相关文章
- [转]EntityFramework的多种记录日志方式,记录错误并分析执行时间过长原因(系列4)
本文转自:https://www.cnblogs.com/GuZhenYin/p/5556732.html Entity Framework 延伸系列目录 今天我们来聊聊EF的日志记录. 一个好的数据 ...
- ActiveMQ的多种部署方式--ActiveMQ学习之二
单点的ActiveMQ作为企业应用无法满足高可用和集群的需求,所以ActiveMQ提供了master-slave.broker cluster等多种部署方式,但通过分析多种部署方式之后我认为需要将两种 ...
- ASP.NET记录错误日志的方式
程序记录错误日志是一种看起来对一般用户没什么作用,但对程序开发者用处很大的东西,它能查出错误或异常的程序马迹.那么,常用的记录错误日志的方式有哪些呢? 大多数情况下使用的是 1.直接记录为txt/xm ...
- asp.net记录错误日志的方法
1.说明 在调试发布后的asp.net项目时有可能会遇到意想不到的错误,而未能及时的显示.这就需要记录日志来跟踪错误信息,所以写了个简单的记录信息的方法,记录简单的文本信息也可以使用.此方法是以生成文 ...
- 点滴积累【C#】---使用log4net组件记录错误日志(以文本形式记录)
效果: 描述: 利用log4net组件进行错误日志的记录,log4net记录错误的方式我所了解的有4种,No.1 文本形式记录日志,No.2存储到数据库形式记录日志,No.3控制台控制显示日志,No. ...
- Python错误 -- try/except/finally 、调用栈、记录错误、抛出错误
Bug:程序编写有问题造成的错误,称之为Bug. debug:调试 注意:bug是程序本身有问题.有缺陷.系统漏洞 异常:完全无法在程序运行中预测的错误,例如写入文件的时候,磁盘满了,写不进去了 ...
- Struts2第十篇【数据校验、代码方式、XML配置方式、错误信息返回样式】
回顾以前的数据校验 使用一个FormBean对象来封装着web端来过来的数据 维护一个Map集合保存着错误信息-对各个字段进行逻辑判断 //表单提交过来的数据全都是String类型的,birthday ...
- Android数据加密概述及多种加密方式 聊天记录及账户加密 提供高质量的数据保护
Android数据加密概述及多种加密方式 聊天记录及账户加密 提供高质量的数据保护 数据加密又称password学,它是一门历史悠久的技术,指通过加密算法和加密密钥将明文转变为密文.而解密则是通过解密 ...
- PHP的日志记录-错误与异常记录
PHP的日志记录-错误与异常记录 提到 Nginx + PHP 服务的错误日志,我们通常能想到的有 Nginx 的 access 日志.error 日志以及 PHP 的 error 日志.虽然看起来是 ...
随机推荐
- RabbitMq应用二
在应用一中,基本的消息队列使用已经完成了,在实际项目中,一定会出现各种各样的需求和问题,rabbitmq内置的很多强大机制和功能会帮助我们解决很多的问题,下面就一个一个的一起学习一下. 消息响应机制 ...
- IE6/7下空div占用空间的问题
最近注意力没在前端上面,工作碰到这样一个问题,下意识的写了句 font-size:0;line-height:0;哪知道引发了更大的bug.后来插入数据进去的时候都不显示了..再后来百度一番找到,原来 ...
- Sublime的使用
1.一个可扩展性强的编辑工具 2.如何安装扩展 通过View->Show Console菜单打开命令行. 按图操作: 在控制台输入,然后回车: import urllib.request,os; ...
- Node.js:dgram模块实现UDP通信
1.什么是UDP? 这里简单介绍下,UDP,即用户数据报协议,一种面向无连接的传输层协议,提供不可靠的消息传送服务.UDP协议使用端口号为不同的应用保留其各自的数据传输通道,这一点非常重要.与TCP相 ...
- 谈谈JS的观察者模式(自定义事件)
呼呼...前不久参加了一个笔试,里面有一到JS编程题,当时看着题目就蒙圈...后来研究了一下,原来就是所谓的观察者模式.就记下来...^_^ 题目 [附加题] 请实现下面的自定义事件 Event 对象 ...
- 【NLP】揭秘马尔可夫模型神秘面纱系列文章(一)
初识马尔可夫和马尔可夫链 作者:白宁超 2016年7月10日20:34:20 摘要:最早接触马尔可夫模型的定义源于吴军先生<数学之美>一书,起初觉得深奥难懂且无什么用场.直到学习自然语言处 ...
- git和pycharm管理代码
首先明白三个概念,服务器代码库,本地代码库,和正在coding的项目. coding完毕后,先通过commit提交到本地代码库,然后通过push再提交server的代码库 git步骤 git c ...
- oracle常用函数及示例
学习oracle也有一段时间了,发现oracle中的函数好多,对于做后台的程序猿来说,大把大把的时间还要学习很多其他的新东西,再把这些函数也都记住是不太现实的,所以总结了一下oracle中的一些常用函 ...
- Prometheus 系统监控方案 一
最近一直在折腾时序类型的数据库,经过一段时间项目应用,觉得十分不错.而Prometheus又是刚刚推出不久的开源方案,中文资料较少,所以打算写一系列应用的实践过程分享一下. Prometheus 是什 ...
- OpenGL ES: Array Texture初体验
[TOC] Array Texture这个东西的意思是,一个纹理对象,可以存储不止一张图片信息,就是说是是一个数组,每个元素都是一张图片.这样免了频繁地去切换当前需要bind的纹理,而且可以节省系统资 ...