应用系统如何分析和获取SQL语句的执行代码

大部分开发人员都有这样一个需求,在程序连接数据库执行时,有时需要获取具体的执行语句,以便进行相关分析,这次我向大家介绍一下通用权限管理系统提供的SQL语句执行跟踪记录,直接先看看代码吧:(这个功能我也是在看底层代码时发现的)

namespace DotNet.Utilities
{
    /// <summary>
    /// SQLTrace
    /// 记录SQL执行 Global 中设置 BaseSystemInfo.LogSQL=true 可以开启跟踪记录
    /// 
    /// 
    /// 修改纪录
    /// 
    ///        2016.01.12 版本:1.0    SongBiao
    ///    
    /// <author>
    ///        <name>SongBiao</name>
    ///        <date>2016.01.12</date>
    /// </author> 
    /// </summary>
    public class SQLTrace
    {
        private static string FileName = "SQLTrace.txt";

        #region public static void WriteLog(string commandText,IDbDataParameter[] dbParameters = null,  string fileName = null) 写入sql查询句日志
        /// <summary>
        /// 写入sql查询句日志
        /// </summary>
        /// <param name="commandText">异常</param>
        /// <param name="dbParameters"></param>
        /// <param name="fileName">文件名</param>
        public static void WriteLog(string commandText, IDbDataParameter[] dbParameters = null, string fileName = null)
        {
            // 系统里应该可以配置是否记录异常现象
            if (!BaseSystemInfo.LogSQL)
            {
                return;
            }
            if (string.IsNullOrEmpty(fileName))
            {
                fileName = DateTime.Now.ToString(BaseSystemInfo.DateFormat) + " _ " + FileName;
            }
            string message = string.Empty;
            message = DateTime.Now.ToString(BaseSystemInfo.DateTimeFormat) + System.Environment.NewLine + "commandText内容" + System.Environment.NewLine + commandText;
            if (dbParameters != null)
            {
                StringBuilder sb = new StringBuilder();
                foreach (var parameter in dbParameters)
                {
                    sb.AppendLine(parameter.ParameterName + "=" + parameter.Value);
                }
                message += System.Environment.NewLine + "dbParameters内容" + System.Environment.NewLine + sb.ToString();
            }
            // 将异常信息写入本地文件中
            string logDirectory = BaseSystemInfo.StartupPath + @"\Log\Query";
            if (!System.IO.Directory.Exists(logDirectory))
            {
                System.IO.Directory.CreateDirectory(logDirectory);
            }
            string writerFileName = logDirectory + "\\" + fileName;
            FileUtil.WriteMessage(message, writerFileName);
        }
        #endregion
    }
}

方法比较简单,传入参数化的SQL语句及参数数组,就可以在文件中记录每次具体的操作语句。如下图:(访问的是MySQL数据库)

【通用权限管理系统中获取某个用户具有的权限(数组)的语句,记录了CommandText和dbParameters两部分,拼接一下就可以执行了】

大家可以参照这个,写出对应的方法记录自己程序访问数据库的语句。

我们来看看在通用权限底层是如何调用这个功能的:

1、在应用程序的Global中加入以下语句,开启日志记录及存储位置设置

            BaseSystemInfo.StartupPath = HttpContext.Current.Server.MapPath("~/");
            BaseSystemInfo.LogSQL = true;

如下图

 

2、调用的一个地方参考

        #region public virtual DataSet Fill(DataSet dataSet, string commandText, string tableName, IDbDataParameter[] dbParameters, CommandType commandType) 填充数据权限
        /// <summary>
        /// 填充数据权限
        /// </summary>
        /// <param name="dataSet">数据权限</param>
        /// <param name="commandType">命令分类</param>
        /// <param name="commandText">sql查询</param>
        /// <param name="tableName">填充表</param>
        /// <param name="dbParameters">参数集</param>
        /// <returns>数据权限</returns>
        public virtual DataSet Fill(DataSet dataSet, string commandText, string tableName, IDbDataParameter[] dbParameters, CommandType commandType)
        {
            // 自动打开
            if (this.DbConnection == null)
            {
                this.Open();
                this.MustCloseConnection = true;
            }
            else if (this.DbConnection.State == ConnectionState.Closed)
            {
                this.Open();
                this.MustCloseConnection = true;
            }

            using (this.dbCommand = this.DbConnection.CreateCommand())
            {
                this.dbCommand.CommandTimeout = this.DbConnection.ConnectionTimeout;
                this.dbCommand.CommandText = commandText;
                this.dbCommand.CommandType = commandType;
                if (this.dbTransaction != null)
                {
                    this.dbCommand.Transaction = this.dbTransaction;
                }

                if ((dbParameters != null) && (dbParameters.Length > 0))
                {
                    for (int i = 0; i < dbParameters.Length; i++)
                    {
                        if (dbParameters[i] != null)
                        {
                            this.dbCommand.Parameters.Add(((ICloneable)dbParameters[i]).Clone());
                        }
                    }

                }

                this.dbDataAdapter = this.GetInstance().CreateDataAdapter();
                this.dbDataAdapter.SelectCommand = this.dbCommand;
                this.dbDataAdapter.Fill(dataSet, tableName);

                SetBackParamValue(dbParameters);

                if (this.MustCloseConnection)
                {
                    this.Close();
                }
                else
                {
                    this.dbDataAdapter.SelectCommand.Parameters.Clear();
                }
            }

            // 记录日志
            SQLTrace.WriteLog(commandText, dbParameters);

            return dataSet;
        }
        #endregion

 

这个功能好好利用,对于分析系统的SQL执行是非常方便的。

 

posted @ 2016-01-12 22:27  三人成虎  阅读(1590)  评论(1编辑  收藏  举报