Entity Framework——记录执行的命令信息
有两种方法可以记录执行的SQl语句:
- 使用DbContext.Database.Log属性
- 实现IDbCommandInterceptor接口
一 使用DbContext.Database.Log属性
下面截图显示了Database属性和Log属性,可以看出这个属性是一个委托,类型为Action<string>


对Log属性的解释为:
Set this property to log the SQL generated by the System.Data.Entity.DbContext to the given delegate. For example, to log to the console, set this property to System.Console.Write(System.String).
使用方法:
1)在自定义上下文中获得执行的SQL相关信息,即在自定上下文的构造函数中使用Database.Log
/// <summary>
/// 自定义上下文
/// </summary>
[DbConfigurationType(typeof(MySqlEFConfiguration))]
public class CustomDbContext : DbContext
{
public CustomDbContext()
: base("name=Master")
{ //this.Configuration.LazyLoadingEnabled = false;
//new DropCreateDatabaseIfModelChanges<CustomDbContext>()
//new DropCreateDatabaseAlways<CustomDbContext>()
Database.SetInitializer<CustomDbContext>(null);
this.Database.Log = Log;
} public DbSet<User> Users { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
EntityConfiguration.Set(modelBuilder);
} private void Log(string cmd)
{
//或输出到控制台
//Console.Write(cmd); //或输出到文件
//using (StreamWriter sw = new StreamWriter(@"E:\EFCmdLogger.txt"))
//{
// sw.WriteLine(cmd);
//} //或输出到调试信息窗口
Debug.WriteLine(cmd);
}
}
执行结果如下截图

2)在具体的方法中使用
public class EFOPerations
{ public static void ReadUser()
{
Stopwatch stw = new Stopwatch();
stw.Start();
using (CustomDbContext db = new CustomDbContext())
{
db.Database.Log = Console.WriteLine;
User user = db.Users.Find();
var userDTO = new { Account = user.Account };
}
stw.Stop();
var time = stw.ElapsedMilliseconds;
}
}
注意
db.Database.Log = Console.WriteLine;这条语句的位置;如果将其放到查询语句,即User user = db.Users.Find(1);之后则无法输出信息!
还可以改变日志的格式:
创建继承自DatabaseLogFormatter的类,实现新的格式化器,然后使用
System.Data.Entity.DbConfiguration.SetDatabaseLogFormatter(System.Func<System.Data.Entity.DbContext,System.Action<System.String>,System.Data.Entity.Infrastructure.Interception.DatabaseLogFormatter>)
DatabaseLogFormatter的三个方法
LogCommand:在SQL 语句或存储过程执行前记录它。
LogParameter:记录参数,默认被LogCommand调用(未能验证这一点)
LogResult:记录SQL 语句或存储过程执行后的一些相关信息
这三个方法包含的参数为:
DbCommand command:SQL 语句或存储过程相关的信息。
DbCommandInterceptionContext<TResult> interceptionContext:执行结果相关的信息。
DbParameter parameter:System.Data.Common.DbCommand 的参数。
重写LogCommand或LogResult都可以改变SQL 语句或存储过程相关信息格式,但是注意这两个方法interceptionContext参数的值可能会不一样。
继承DatabaseLogFormatter,实现格式化器
public class CustomDatabaseLogFormatter : DatabaseLogFormatter
{
public CustomDatabaseLogFormatter(DbContext context, Action<string> writeAction)
: base(context, writeAction)
{
}
public override void LogCommand<TResult>(DbCommand command, DbCommandInterceptionContext<TResult> interceptionContext)
{ } public override void LogResult<TResult>(DbCommand command, DbCommandInterceptionContext<TResult> interceptionContext)
{
StringBuilder sb = new StringBuilder();
for (int i = ; i < command.Parameters.Count; i++)
{
sb.AppendLine(string.Format("参数名称:{0},值:{1}", command.Parameters[].ParameterName, command.Parameters[].Value));
}
Write(command.CommandText + Environment.NewLine
+ command.CommandTimeout + Environment.NewLine
+ command.CommandType + Environment.NewLine
+ Environment.NewLine
+ sb.ToString());
}
}
设置新的格式化器
public class CustomDbConfiguration : MySqlEFConfiguration
{
public CustomDbConfiguration():base()
{
//this.AddInterceptor(new CommandInterceptor(new Logger()));
SetDatabaseLogFormatter((context, writeAction) => new CustomDatabaseLogFormatter(context, writeAction));
}
}
使用自定义CustomDbConfiguration
[DbConfigurationType(typeof(CustomDbConfiguration))]
public class CustomDbContext : DbContext
{
public CustomDbContext()
: base("name=Master")
{ //this.Configuration.LazyLoadingEnabled = false;
//new DropCreateDatabaseIfModelChanges<CustomDbContext>()
//new DropCreateDatabaseAlways<CustomDbContext>()
Database.SetInitializer<CustomDbContext>(null);
this.Database.Log = Log;
} ...... }
二 实现IDbCommandInterceptor接口
实现IDbCommandInterceptor,同时为了灵活的记录执行信息,定义了日志接口
public class CommandInterceptor : IDbCommandInterceptor
{
private ICommandLogger logger;
public CommandInterceptor(ICommandLogger logger)
{
this.logger = logger;
}
public void NonQueryExecuted(DbCommand command, DbCommandInterceptionContext<int> interceptionContext)
{
this.logger.Log<int>(command, interceptionContext);
} public void NonQueryExecuting(DbCommand command, DbCommandInterceptionContext<int> interceptionContext)
{
this.logger.Log<int>(command, interceptionContext);
} public void ReaderExecuted(DbCommand command, DbCommandInterceptionContext<System.Data.Common.DbDataReader> interceptionContext)
{
this.logger.Log<DbDataReader>(command, interceptionContext);
} public void ReaderExecuting(DbCommand command, DbCommandInterceptionContext<System.Data.Common.DbDataReader> interceptionContext)
{
this.logger.Log<DbDataReader>(command, interceptionContext);
} public void ScalarExecuted(DbCommand command, DbCommandInterceptionContext<object> interceptionContext)
{
this.logger.Log<object>(command, interceptionContext);
} public void ScalarExecuting(DbCommand command, DbCommandInterceptionContext<object> interceptionContext)
{
this.logger.Log<object>(command, interceptionContext);
}
} public interface ICommandLogger
{
void Log<T>(DbCommand command, DbCommandInterceptionContext<T> interceptionContext);
} public class Logger : ICommandLogger
{
public void Log<T>(System.Data.Common.DbCommand command, System.Data.Entity.Infrastructure.Interception.DbCommandInterceptionContext<T> interceptionContext)
{
StringBuilder sb = new StringBuilder();
for(int i =;i<command.Parameters.Count;i++)
{
sb.AppendLine(string.Format("参数名称:{0},值:{1}", command.Parameters[].ParameterName, command.Parameters[].Value));
} Debug.WriteLine(command.CommandText+Environment.NewLine
+ command.CommandTimeout + Environment.NewLine
+ command.CommandType + Environment.NewLine
+ Environment.NewLine
+ sb.ToString());
}
}
如何使用这两个类呢?
1使用配置文件
<entityFramework>
<interceptors>
<interceptor type="ConsoleApp_EntityFramework.Interceptor.CommandInterceptor, ConsoleApp_EntityFramework.Interceptor">
</interceptor>
</interceptors>
</entityFramework>
但是采用这种方式要对上面的CommandInterceptor 进行改造。
public class CommandInterceptor : IDbCommandInterceptor
{
private ICommandLogger logger;
public CommandInterceptor()
{
this.logger = new Logger();
} ......
}
但是如果EF操作的是Mysql那么这种方法不行,抛出异常:无法识别的元素“interceptors”
2编码方式
只有上面两个类还不够,还要定义创建一个继承自DbConfiguration的配置类
public class CustomDbConfiguration : DbConfiguration
{
public CustomDbConfiguration():base()
{
this.AddInterceptor(new CommandInterceptor(new Logger()));
}
}
在自定义数据库上下文上使用此特性
/// <summary>
/// 自定义上下文
/// </summary>
[DbConfigurationType(typeof(CustomDbConfiguration))]
public class CustomDbContext : DbContext
{
......
}
一切准备好后运行程序,却抛出异常:
The ADO.NET provider with invariant name 'MySql.Data.MySqlClient' is either not registered in the machine or application config file, or could not be loaded. See the inner exception for details.
似乎是MySql.Data.MySqlClient的问题,其实不是!
如果是SQL Server则没问题,但这里EF框架操作的是MySql,要是使用MySql.Data.Entity.MySqlEFConfiguration这个类,而不是System.Data.Entity.DbConfiguration,所以CustomDbConfiguration应该派生自MySql.Data.Entity.MySqlEFConfiguration
public class CustomDbConfiguration : MySqlEFConfiguration
{
public CustomDbConfiguration():base()
{
this.AddInterceptor(new CommandInterceptor(new Logger()));
}
.....
}
这样修改后,运行程序得到下面的结果:

可以看到日志打印了两次,这是因为ReaderExecuting和ReaderExecuted各调用了一次,执行的顺序是先ReaderExecuting然后ReaderExecuted。
-----------------------------------------------------------------------------------------
转载与引用请注明出处。
时间仓促,水平有限,如有不当之处,欢迎指正。
Entity Framework——记录执行的命令信息的更多相关文章
- [翻译] - <Entity Framework> - 直接执行数据库命令
原文:[翻译] - <Entity Framework> - 直接执行数据库命令 纯属学习上的记录, 非专业翻译, 如有错误欢迎指正! 原文地址: http://msdn.microsof ...
- 关于MySql entity framework 6 执行like查询问题解决方案
原文:关于MySql entity framework 6 执行like查询问题解决方案 本人不善于言辞,直接开门见山 环境:EF6.0.0.0+MySQL Server5.6+MySqlConnec ...
- 在Entity Framework 中执行T-sql语句
从Entity Framework 4开始在ObjectContext对象上提供了2个方法可以直接执行SQL语句:ExecuteStoreQuery<T> 和 ExecuteStoreC ...
- Entity Framework Core 执行SQL语句和存储过程
无论ORM有多么强大,总会出现一些特殊的情况,它无法满足我们的要求.在这篇文章中,我们介绍几种执行SQL的方法. 表结构 在具体内容开始之前,我们先简单说明一下要使用的表结构. public clas ...
- java记录linux top命令信息
import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.Fi ...
- Entity Framework 6 执行Linq to Entities异常"p__linq__1 : String truncation: max=0, len=2, value='测试'"
场景再现 我需要查询公司名称包含给定字符串的公司,于是我写了下面的测试小例子: var condition = "测试"; var query = from b in db.Com ...
- Entity Framework中执行Sql语句
如果想在EF框架中执行Sql语句,其实很简单,EF里面已经提供了相关的方法(此处使用的EF为EF4.1版本). EF中提供了两个方法,一个是执行查询的Sql语句SqlQue ...
- Entity FrameWork Code First 迁移命令详解
1. Enable-Migrations 启动迁移 执行get-help Enable-Migrations –detailed 查看Enable-Migrations的详细用法. -ContextT ...
- .NET Entity Framework(EF)使用SqlQuery直接操作SQL查询语句或者执行过程
Entity Framework是微软出品的高级ORM框架,大多数.NET开发者对这个ORM框架应该不会陌生.本文主要罗列在.NET(ASP.NET/WINFORM)应用程序开发中使用Entity F ...
随机推荐
- 动态添加div及对应的js、css文件
动态添加div及对应的js.css文件 在近期的项目开发中需要在首页中添加很多面板型的div,直接加载代码显得很繁琐,于是利用js封装一个动态添加div及其对应css文件和js文件的方法供大家参考使用 ...
- spring 事务隔离级别配置
声明式的事务处理中,要配置一个切面,即一组方法,如 其中就用到了propagation,表示打算对这些方法怎么使用事务,是用还是不用,其中propagation有七种配置,REQUIRED.SUPPO ...
- Nginx日志中的金矿 -- 好文收藏
转:http://www.infoq.com/cn/articles/nignx-log-goldmine Nginx(读作Engine-X)是现在最流行的负载均衡和反向代理服务器之一.如果你是一名中 ...
- java—— finall 关键词
_ *{ margin: 0; padding: 0; } .on2{ margin: 10px 0; cursor: pointer; user-select: none; color: white ...
- Django 中 makemigrations、migrate时 No changes detected
Django创建的项目中,需要更改.增加.删除表中的某些属性,性急直接把之前数据库表删除了,之后再执行: python manage.py makemigrations python manage.p ...
- Servlet和web服务器关系
前面的博客我详细的罗列了下Servlet的常用的类和接口,然后在前面的前面我类似tomcat模拟了一套web服务器,这里来做一个统一的整理,这样子可以更好的把握Servlet,也可以更好的了解下web ...
- Windows 产品激活状态、密钥等信息查看
目前,大多PC都是预装了微软家的桌面级系统 Windows ,这也算是微软一大得意之作.可是 Windows 产品可不是免费的,是要 $ 的.可能在中国,大多数系统可能是盗版过来的,像当年的雨林木风( ...
- Python Django连接(听明白了是连接不是创建!)Mysql已存在的数据库
再声明一次!是连接不是创建!网上的一些人难道连接和创建这俩词都弄不懂就在那里瞎写一些文章! (Python Django连接存在的数据库) Python连接存在的数据库-------MySql 1.首 ...
- hibernate 基础
Hibernate:是开源的ORM框架技术,对jdbc进行了非常轻量级的对象封装,处于业务逻辑层和数据库层之间,称作持久化层. 持久化层的作用:把程序生成的对象持久化到数据库,也就是保存到数据库. ...
- 跟我一起读postgresql源码(十五)——Executor(查询执行模块之——control节点(上))
控制节点 控制节点用于完成一些特殊的流程执行方式.由于PostgreSQL为査询语句生成二叉树状的査询计划,其中大部分节点的执行过程需要两个以内的输入和一个输出.但有一些特殊的功能为了优化的需要,会含 ...