发布网友 发布时间:2022-04-30 20:33
共2个回答
懂视网 时间:2022-05-01 00:55
那么问题来了,我们该如何正确这个时间呢?此问题又可以细分为两个步骤。
(1)如何知道SQL命令是正在执行时以及执行完成呢?
(2)知道了之后我们又如何设置以及获取时间呢?
我们一一来划分,首先我建立一个类 SQLProfiler ,而此类肯定是继承于 DbCommandInterceptor ,所以代码就变成了这样。
public class SQLProfiler : DbCommandInterceptor { public override void ReaderExecuting(DbCommand command, DbCommandInterceptionContext<DbDataReader> interceptionContext) { Executing(interceptionContext); base.ReaderExecuting(command, interceptionContext); } public override void ReaderExecuted(DbCommand command, DbCommandInterceptionContext<DbDataReader> interceptionContext) { Executed(command, interceptionContext); base.ReaderExecuted(command, interceptionContext); } public override void NonQueryExecuting(DbCommand command, DbCommandInterceptionContext<int> interceptionContext) { Executing(interceptionContext); base.NonQueryExecuting(command, interceptionContext); } public override void NonQueryExecuted(DbCommand command, DbCommandInterceptionContext<int> interceptionContext) { Executed(command, interceptionContext); base.NonQueryExecuted(command, interceptionContext); } public override void ScalarExecuting(DbCommand command, DbCommandInterceptionContext<object> interceptionContext) { Executing(interceptionContext); base.ScalarExecuting(command, interceptionContext); } public override void ScalarExecuted(DbCommand command, DbCommandInterceptionContext<object> interceptionContext) { Executed(command, interceptionContext); base.ScalarExecuted(command, interceptionContext); } }
貌似发现了什么,好像方法参数都是什么DbCommand和DbCommandInterCeptionContext,既然这样,我们依样画葫芦诺,为了从执行SQL命令开始,我们此时从这里开始计时,将计时对象给UserState即可,于是就有了下面的代码。
private void Executing<T>(DbCommandInterceptionContext<T> interceptionContext) { var timer = new Stopwatch(); interceptionContext.UserState = timer; timer.Start(); }
此时应该就明朗了,我们在执行完成后来获取该计时对象并利用是否出现异常和我们指定设置的时间来判断其最终所花费的时间。执行完成后代码如下:
private void Executed<T>(DbCommand command, DbCommandInterceptionContext<T> interceptionContext) { var timer = (Stopwatch)interceptionContext.UserState; timer.Stop(); if (interceptionContext.Exception != null) { File.AppendAllLines( _logFile, new string[] { "错误SQL语句", interceptionContext.Exception.Message, command.CommandText, Environment.StackTrace, string.Empty, string.Empty, }); } else if (timer.ElapsedMilliseconds >= _executionTime) { File.AppendAllLines( _logFile, new string[] { string.Format("耗时SQL语句({0}ms)",timer.ElapsedMilliseconds), command.CommandText, Environment.StackTrace, string.Empty, string.Empty, }); } }
上述 _executionTime 是我们在此类构造函数中所设置的时间,构造函数如下:
private readonly string _logFile; private readonly int _executionTime; public SQLProfiler(string logFile, int executionTime) { _logFile = logFile; _executionTime = executionTime; }
而logFile则是我么所要输出的日志。此时别忘记最重要的一件事,那就是DbConfiguration配置类中进行注册(或者在配置文件中进行注册)。如下:
public class MyDbConfiguration : DbConfiguration { public MyDbConfiguration() { this.AddInterceptor(new SQLProfiler(@"D:log.txt", 1)); } }
接下来我们来进行检验结果。
using (var ctx = new EntityDbContext()) { SqlParameter[] parameter = { }; ctx.Database.SqlQuery<Student>("select * from a", parameter).ToList(); Console.ReadKey(); }
上述表a实际上是不存在的,我们就是要看看是否能检测到该异常并获取其时间。来,瞧一瞧。
【效果一】
【效果二】
当然,如上述当执行查询时此表不存在肯定是会报错,但是我们的侧重点不在此,这里验证了此表不存在,同时也验证了SQL在执行时和执行完之间的耗时,同时我们可以通过构造函数手动设置当耗时大于我们预期的多少才算需要改善SQL。
EntityFramework之监听者判断SQL性能指标
标签:
热心网友 时间:2022-04-30 22:03
单从实现方式上来讲应该是entity framework效率更高,虽然我从没用过,也很少使用linq,entity framework是一套orm框架,类似的还有很多,而linq to sql 是在orm的基础上再去使用linq特性实现某个功能,相对基础语法,linq的使用只是减少了代码,却影响了性能。所以我认为linq to sql性能会差一些。但是,这也取决于两套东西内部具体的实现和应用,尤其应用在大数据量的场景中才能比较出差异。各有优劣,这样看来这个提问有点过于笼统了哦。 所以具体的应用还要看具体的需求,单独讲性能的话还是基础语法来的最快。