实体框架6 - 定时查询

Yog*_*esh 14 c# sql-server entity-framework entity-framework-6

我正在使用Entity Framework 6,它是一个非常棒的数据库拦截器功能,用于记录从应用程序数据库发送的查询.但是,我正在努力为这些查询计时,我有一个长时间运行的查询,返回数十万到数百万行,因此需要大约6到15秒,具体取决于此查询将返回的数据量.实体框架返回一个SqlDataReader,因为我无法获得获取结果所需的确切时间.我想知道从查询发送到读取最后一行的时间的完整执行时间.有没有办法可以做到.

Jon*_*len 26

这是我通常用于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} \r\nCommand:\r\n{2}", duration.TotalSeconds.ToString("N3"), requestId, parameters.ToString() + command.CommandText);
        }
        else
        {
            message = string.Format("EF Database call failed after {0} sec. RequestId {1} \r\nCommand:\r\n{2}\r\nError:{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);
    }
}
Run Code Online (Sandbox Code Playgroud)

不幸的是,文档不存在,所以我不知道这是否适用于您的场景.

  • 我问其他地方:http://stackoverflow.com/q/40339358/1380710.奇怪的时机是因为`DateTime`不能保证准确度高于系统计时器,对于Windows NT是10ms,而Windows 8+则是1ms.我不得不使用`System.Diagnostics.Stopwatch`来获得更高的精度. (4认同)
  • @Jonathan Allen你使用requestId做什么? (3认同)
  • PS我上面的示例缺少从HttpContext.Current读取的代码以获取真实的请求ID.-1是数据库调用的占位符,不依赖于Web请求. (2认同)
  • 这里的一些文档https://msdn.microsoft.com/en-us/data/dn469464.aspx (2认同)