应用系统如何分析和获取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执行是非常方便的。