private void App_PostRequestHandlerExecute(object sender, EventArgs e)
        {
            HttpApplication app = (HttpApplication)sender;

            string headerValue = app.Request.Headers["X-Fiddler-Profiler"];

            if (string.IsNullOrEmpty(headerValue))
            {
                return;
            }

            if (headerValue.IndexOf("ar") >= 0)
            {
                // 输入一个响应头,回应Fiddler插件,可用于分析不规范请求的响应头
                app.Response.Headers.Add("X-Fiddler-AnalyzeRequest", "OK");
            }



            List <DbActionInfo> list = app.Context.Items[ContextItemKey] as List <DbActionInfo>;

            if (list == null || list.Count == 0)
            {
                return;
            }


            // 计算数据库连接打开次数
            int connectionCount = 0;

            foreach (var info in list)
            {
                if (info.SqlText == DbActionInfo.OpenConnectionFlag)
                {
                    connectionCount++;
                }
            }

            // 打开数据库的连接次数
            app.Response.Headers.Add("X-SQL-ConnectionCount", connectionCount.ToString());


            // 数据访问监控的响应头
            int index = 1;

            foreach (DbActionInfo info in list)
            {
                string base64     = DbActionInfo.Serialize(info);
                string headerName = "X-SQL-Action-" + (index++).ToString();
                app.Response.Headers.Add(headerName, base64);
            }
        }
        private DbActionInfo ConvertToDbActionInfo(DbCommand command)
        {
            if (_startTime.HasValue == false)
            {
                return(null);
            }

            // 注意:这里会对SQL语句做截断处理,因为有些场景下某些开发人员能拼接出好几M的SQL,
            // 影响网络传输和界面展示。

            DbActionInfo info = new DbActionInfo();

            info.Time          = DateTime.Now - _startTime.Value;       // 计算执行时间
            info.SqlText       = command.CommandText.KeepLength(1024 * 1024 * 2);
            info.InTranscation = command.Transaction != null;           // 判断是否在事务中
            info.Parameters    = new List <CommandParameter>();

            // 提取命令参数
            for (int i = 0; i < command.Parameters.Count; i++)
            {
                if (i < 64)                     // 只提取64个参数
                {
                    DbParameter parameter = command.Parameters[i];

                    CommandParameter p = new CommandParameter();
                    p.Name   = parameter.ParameterName;
                    p.DbType = parameter.DbType.ToString();
                    if (parameter.Value != null)
                    {
                        p.Value = parameter.Value.ToString().KeepLength(128);                         // 也做截断处理
                    }
                    else
                    {
                        p.Value = "NULL";
                    }

                    info.Parameters.Add(p);
                }
                else
                {
                    // 防止在拼接IN条件,出现上千个参数!
                    CommandParameter p = new CommandParameter();
                    p.Name   = "#####";
                    p.DbType = "#####";
                    p.Value  = "参数太多,已被截断...,参数数量:" + command.Parameters.Count.ToString();
                    info.Parameters.Add(p);
                    break;
                }
            }

            return(info);
        }
        private void Instance_ConnectionOpened(object sender, ConnectionEventArgs e)
        {
            List <DbActionInfo> list = GetDbActionInfoList();

            if (list == null)
            {
                return;
            }

            DbActionInfo info = new DbActionInfo();

            // 一个特殊的字符串,标记是一个打开连接的操作,后面会在FiddlerPulgin中判断它
            info.SqlText = DbActionInfo.OpenConnectionFlag;
            list.Add(info);
        }
        private void Instance_AfterExecute(object sender, CommandEventArgs e)
        {
            List <DbActionInfo> list = GetDbActionInfoList();

            if (list == null)
            {
                return;
            }

            DbActionInfo info = ConvertToDbActionInfo(e.DbCommand);

            if (info != null)
            {
                list.Add(info);
            }
        }
        private void Instance_OnException(object sender, ExceptionEventArgs e)
        {
            List <DbActionInfo> list = GetDbActionInfoList();

            if (list == null)
            {
                return;
            }


            DbActionInfo info = ConvertToDbActionInfo(e.DbCommand);

            if (info != null)
            {
                info.ErrorMsg = e.Exception.GetBaseException().Message;
                list.Add(info);
            }
        }