如何在C# .NET调试器中获取参数化查询替换参数后的实际执行SQL
实现方案
方案1:调试器即时窗口直接生成可运行SQL
在调用ExecuteMyLikeQueryTerms的代码行打断点,命中断点后在即时窗口运行以下参数替换逻辑,回车即可直接输出拼接完成的SQL:
- 先确认
parameters参数为SqlParameter[]或IEnumerable<SqlParameter>类型,在即时窗口输入代码:
var tempSql = query; foreach (SqlParameter p in parameters) { string valueStr; if (p.Value == DBNull.Value) { valueStr = "NULL"; } else { switch (p.SqlDbType) { case SqlDbType.Char: case SqlDbType.NChar: case SqlDbType.VarChar: case SqlDbType.NVarChar: case SqlDbType.Text: case SqlDbType.NText: case SqlDbType.Date: case SqlDbType.DateTime: case SqlDbType.DateTime2: case SqlDbType.SmallDateTime: valueStr = $"'{p.Value.ToString().Replace("'", "''")}'"; break; case SqlDbType.Bit: valueStr = (bool)p.Value ? "1" : "0"; break; default: valueStr = p.Value.ToString(); break; } } tempSql = tempSql.Replace(p.ParameterName, valueStr); } tempSql
输出的tempSql就是参数全部替换完成的语句,可直接复制到SQL Server运行。
方案2:封装扩展方法一劳永逸
如果频繁需要查看生成的SQL,可以给参数集合写扩展方法,调试时直接调用即可:
- 新建静态类添加扩展方法:
public static class SqlExtensions { public static string ToRunnableSql(this string query, IEnumerable<SqlParameter> parameters) { var result = query; foreach (var p in parameters) { string formattedValue; if (p.Value == DBNull.Value) { formattedValue = "NULL"; } else if (p.SqlDbType is SqlDbType.DateTime or SqlDbType.DateTime2 or SqlDbType.Date or SqlDbType.SmallDateTime) { formattedValue = $"'{((DateTime)p.Value).ToString("yyyy-MM-dd HH:mm:ss.fff")}'"; } else if (p.SqlDbType is SqlDbType.NChar or SqlDbType.NVarChar or SqlDbType.Char or SqlDbType.VarChar or SqlDbType.Text or SqlDbType.NText) { formattedValue = $"'{p.Value.ToString().Replace("'", "''")}'"; } else if (p.SqlDbType == SqlDbType.Bit) { formattedValue = (bool)p.Value ? "1" : "0"; } else { formattedValue = p.Value.ToString(); } result = result.Replace(p.ParameterName, formattedValue); } return result; } }
- 调试时在即时窗口直接输入
query.ToRunnableSql(parameters),回车即可拿到可运行的SQL语句。
方案3:使用SQL Server Profiler抓实际执行语句
不需要修改代码的情况下,直接打开SQL Server Profiler,连接到目标数据库开启跟踪后触发代码执行查询,就能直接捕获到参数替换完成后、实际发送到SQL Server运行的完整语句,不需要自己处理参数转换逻辑。
注意:如果参数包含二进制类型,需要额外补充对应类型的转换分支,常规业务场景的常见类型上述代码已经完全覆盖。
内容的提问来源于stack exchange,提问作者cdub
相关产品推荐
相关产品推荐

