写出易调试的SQL—西科软件

时间:2024-04-07 19:06:25

1.前言

上篇 写出易调试的SQL , 带来了一些讨论, 暴露了不能重用执行计划和sql注入问题, 十分感谢园友们的建议 .

经过调整后 ,将原来的SQLHelper 抓SQL 用做调试环境用, 发布环境还是走Dapper的参数化查询, 保持原有优势.

见如下代码.

2. 在开发调试阶段 抓最终SQL

将Dapper 查询Query 和执行Execute 进行了再包装, 插入了 抓最终sql 的代码

写出易调试的SQL—西科软件
 public class DapperTaller
    {

        /// <summary>
        /// dapper 执行查询 sql
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="sql"></param>
        /// <param name="param"></param>
        /// <returns></returns>
        public static IEnumerable<T> Query<T>(string sql, object param)
        {
            IEnumerable<T> result = null;
            using (var con = DBHelper.GetConnection())
            {
                result = con.Query<T>(sql, param);
            }

            //开发环境代码
            if (GlobalVariable.env.IsDevelopment()) //IsDevelopment 方法为Asp.NET Core 自带的 是否为开发环境的判断方法
            {
                //最终SQL
                var debugSql = GetDebugSQL(sql, param);
                Debug.WriteLine(debugSql);
            }

            return result;
        }

        /// <summary>
        /// dapper 执行 增加, 删除 ,修改 sql
        /// </summary>
        /// <param name="sql"></param>
        /// <param name="param"></param>
        /// <returns></returns>
        public static int Execute(string sql, object param)
        {
            int result;
            using (var con = DBHelper.GetConnection())
            {
                result = con.Execute(sql, param);
            }

            //开发环境代码
            if (GlobalVariable.env.IsDevelopment()) //IsDevelopment 方法为Asp.NET Core 自带的 是否为开发环境的判断方法
            {
                //最终SQL
                var debugSql = GetDebugSQL(sql, param);
                Debug.WriteLine(debugSql);
            }

            //生产环境代码
            if (GlobalVariable.env.IsProduction())
            {
                //根据需要将最终SQL 记录到日志

            }

            return result;
        }

        public static string GetDebugSQL(string sql, object param)
        {
            var sqlHelper = new SqlHelper();
            foreach (var item in param.GetType().GetProperties())
            {
                var name = item.Name;
                var value = item.GetValue(param);
                sqlHelper.Param.Add(name, value);
            }

            sqlHelper.ReplaceParam(ref sql);
            return sql;
        }

    }

    public class DBHelper
    {
        public static IDbConnection GetConnection()
        {
            return SQLServerHelper.GetConnection();
        }
    }
写出易调试的SQL—西科软件

调用代码:

写出易调试的SQL—西科软件
 public IEnumerable<Ptype> GetPtypeDetail()
        {
            var sql = @"
 SELECT
    *
 FROM dbo.CoacherStudentMoney a
 INNER JOIN dbo.BaseData b ON a.CourseTypeId=b.Id
 WHERE
 StudentUserId=@StudentUserId AND Amount=@Amount
 AND IsPay=@IsPay AND CreateDate=@CreateDate

";
            var param = new
            {
                StudentUserId = "001",
                CreateDate = DateTime.Now,
                Amount = 3,
                IsPay = true
            };

            IEnumerable<Ptype> plist = new List<Ptype>();
            plist = DapperTaller.Query<Ptype>(sql, param);

            return plist;
        }
写出易调试的SQL—西科软件

最上面代码的此处为最终SQL 抓取

写出易调试的SQL—西科软件
          //开发环境代码
            if (GlobalVariable.env.IsDevelopment())
            {
                //最终SQL
                var debugSql = GetDebugSQL(sql, param);
                Debug.WriteLine(debugSql);
            }
    
写出易调试的SQL—西科软件

并且会在VS 的输出窗口输出

写出易调试的SQL—西科软件

进一步方便了调试.

3.最后

现在最终SQL 的抓取发生在 调试开发阶段 .

发布代码后, 将不会进行最终SQL的抓取. 并且走的还是Dapper 原有参数化查询的方式, 依旧拥有执行计划重用, 防SQL注入的优势.