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());
}