问题描述
我正在使用 Entity Framework 6,它是很棒的数据库拦截器功能,用于记录从应用程序发送到数据库的查询.但是,我正在努力为这些查询计时,我有一个长时间运行的查询,它返回数十万到数百万行,因此它需要大约 6 到 15 秒,具体取决于该查询将返回的数据量.实体框架正在返回一个 SqlDataReader,因此我无法获得获得结果所需的确切时间.我想知道从发送查询到读取最后一行的完整执行时间.有什么办法可以吗.
I am using Entity Framework 6 and it's awesome database interceptor features to log queries which are being sent from application the database. However, I am struggling to time those queries, I have a long running query which returns hundred of thousands to millions of rows so it takes around 6 to 15 seconds depending on the amount of data this query is going to return. Entity framework is returning a SqlDataReader because of which I cannot get the exact time it takes to get the result. I want to know the complete execution time from the time query was sent to the time last row was read. Is there a way I can do it.
推荐答案
这里是我通常用于 EF 的 logger.
Here is the logger I usually use for EF.
public class EFLoggerForTesting : IDbCommandInterceptor
{
static readonly ConcurrentDictionary<DbCommand, DateTime> m_StartTime = new ConcurrentDictionary<DbCommand, DateTime>();
public void ReaderExecuted(DbCommand command, DbCommandInterceptionContext<DbDataReader> interceptionContext)
{
Log(command, interceptionContext);
}
public void NonQueryExecuted(DbCommand command, DbCommandInterceptionContext<int> interceptionContext)
{
Log(command, interceptionContext);
}
public void ScalarExecuted(DbCommand command, DbCommandInterceptionContext<object> interceptionContext)
{
Log(command, interceptionContext);
}
private static void Log<T>(DbCommand command, DbCommandInterceptionContext<T> interceptionContext)
{
DateTime startTime;
TimeSpan duration;
if (m_StartTime.TryRemove(command, out startTime))
{
duration = DateTime.Now - startTime;
}
else
duration = TimeSpan.Zero;
var requestId =-1;
string message;
var parameters = new StringBuilder();
foreach (DbParameter param in command.Parameters)
{
parameters.AppendLine(param.ParameterName + " " + param.DbType + " = " + param.Value);
}
if (interceptionContext.Exception == null)
{
message = string.Format("Database call took {0} sec. RequestId {1}
Command:
{2}", duration.TotalSeconds.ToString("N3"), requestId, parameters.ToString() + command.CommandText);
}
else
{
message = string.Format("EF Database call failed after {0} sec. RequestId {1}
Command:
{2}
Error:{3} ", duration.TotalSeconds.ToString("N3"), requestId, parameters.ToString() + command.CommandText, interceptionContext.Exception);
}
Debug.WriteLine(message);
}
public void NonQueryExecuting(DbCommand command, DbCommandInterceptionContext<int> interceptionContext)
{
OnStart(command);
}
public void ReaderExecuting(DbCommand command, DbCommandInterceptionContext<DbDataReader> interceptionContext)
{
OnStart(command);
}
public void ScalarExecuting(DbCommand command, DbCommandInterceptionContext<object> interceptionContext)
{
OnStart(command);
}
private static void OnStart(DbCommand command)
{
m_StartTime.TryAdd(command, DateTime.Now);
}
}
不幸的是,该文档不存在,所以我不知道这是否适用于您的场景.
Unfortunately the documentation is non-existent so I don't know if this will work for your scenario.
这篇关于实体框架 6 - 定时查询的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!