1、前言:用linq配合ef做数据相关操作时,如果我们想得到所生成的sql,大概可以像这样。
(1)用.ToTraceString(),当然你要把先把查询语句的类型转成ObjectQuery<T>类型。
var query = from s in context.Students
where s.Name == "张三"
select s;
ObjectQuery<Student> studentsQuery = query as ObjectQuery<Student>;
string sql = studentsQuery.ToTraceString();//sql就是生成的sql语句
(2)在EF 4之后,我们可以直接调用DbQuery<>的ToString()方法得到所生成的SQL。也就是上面的studentsQuery直接ToString
string sql = studentsQuery.ToTraceString();//可以猜到,这里的ToString()方法其实也就是调用了ObjectQuery<>的ToTraceString()方法。
(3)上面的方法我们无法得到新增或者删除数据时生成的sql。如果想得到这写操作生成的sql,EF6.1给我们提供了相应的方法。
2、EF6.1也出来不少日子了,6.1相比6.0有个很大的特点就是新增了System.Data.Entity.Infrastructure.Interception 命名空间,此命名空间下的对象可以允许我们更加方便的了解到EF运行时的一些信息,当然我们最想看的还是EF生成的Sql语句。
2.1 首先要写一个类继承DbCommandInterceptor。
using System.Data.Entity.Infrastructure.Interception;
using System.Diagnostics;
class EFIntercepterLogging : DbCommandInterceptor
{
private readonly Stopwatch _stopwatch = new Stopwatch();
public override void ScalarExecuting(System.Data.Common.DbCommand command, DbCommandInterceptionContext<object> interceptionContext)
{
//var sql = command.CommandText;//这里可以获得想要的sql语句
base.ScalarExecuting(command, interceptionContext);
_stopwatch.Restart();
}
public override void ScalarExecuted(System.Data.Common.DbCommand command, DbCommandInterceptionContext<object> interceptionContext)
{
_stopwatch.Stop();
if (interceptionContext.Exception != null)
{
Trace.TraceError("Exception:{1} rn --> Error executing command: {0}", command.CommandText, interceptionContext.Exception.ToString());
}
else
{
Trace.TraceInformation("rn执行时间:{0} 毫秒rn-->ScalarExecuted.Command:{1}rn", _stopwatch.ElapsedMilliseconds, command.CommandText);
}
base.ScalarExecuted(command, interceptionContext);
}
public override void NonQueryExecuting(System.Data.Common.DbCommand command, DbCommandInterceptionContext<int> interceptionContext)
{
base.NonQueryExecuting(command, interceptionContext);
_stopwatch.Restart();
}
public override void NonQueryExecuted(System.Data.Common.DbCommand command, DbCommandInterceptionContext<int> interceptionContext)
{
_stopwatch.Stop();
if (interceptionContext.Exception != null)
{
Trace.TraceError("Exception:{1} rn --> Error executing command:rn {0}", command.CommandText, interceptionContext.Exception.ToString());
}
else
{
Trace.TraceInformation("rn执行时间:{0} 毫秒rn-->NonQueryExecuted.Command:rn{1}", _stopwatch.ElapsedMilliseconds, command.CommandText);
}
base.NonQueryExecuted(command, interceptionContext);
}
public override void ReaderExecuting(System.Data.Common.DbCommand command, DbCommandInterceptionContext<System.Data.Common.DbDataReader> interceptionContext)
{
base.ReaderExecuting(command, interceptionContext);
_stopwatch.Restart();
}
public override void ReaderExecuted(System.Data.Common.DbCommand command, DbCommandInterceptionContext<System.Data.Common.DbDataReader> interceptionContext)
{
_stopwatch.Stop();
if (interceptionContext.Exception != null)
{
Trace.TraceError("Exception:{1} rn --> Error executing command:rn {0}", command.CommandText, interceptionContext.Exception.ToString());
}
else
{
Trace.TraceInformation("rn执行时间:{0} 毫秒 rn -->ReaderExecuted.Command:rn{1}", _stopwatch.ElapsedMilliseconds, command.CommandText);
}
base.ReaderExecuted(command, interceptionContext);
}
}
2.1.1 上面的command.CommandText就是捕获的sql语句。
从方法名我们可以看出大致就三类:读取类的sql,[Reader],非读取类的sql,[NonQuery],还有[Scalar],这类用的比较少,跟原始的ADO.NET命令类型基本一样,不多讲.每个sql语句类型的方法都有执行前Executing,执行后Executed
2.2 然后要在程序的入口(Application_Start)注册一条监听器
void Application_Start(object sender, EventArgs e)
{
DbInterception.Add(new EFIntercepterLogging());
}