EntityFramework的记录日志方式以及记录错误并分析执行时间过长原因是什么,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。
今天我们来聊聊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语句和错误信息
rivate 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;
} elseduration = 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的记录日志方式以及记录错误并分析执行时间过长原因是什么问题的解答就分享到这里了,希望以上内容可以对大家有一定的帮助,如果你还有很多疑惑没有解开,可以关注亿速云行业资讯频道了解更多相关知识。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。