从.NET可以获得由SqlCommand对象生成的完整SQL字符串(使用SQL参数)吗?

Joh*_*n K 6 sql-server reflection ado.net sqlcommand

从.NET环境中,我可以访问由SqlCommand对象生成的完整SQL字符串吗?

注意:在调试模式下,完整的SQL字符串显示在VisualStudio中的Intellisense悬停中.

如果必须,我愿意使用反射技术.我相信这里有人知道如何做到这一点.


更新1:
我正在调用具有参数的存储过程,cmd.CommandType = CommandType.StoredProcedure并且我正在尝试获取生成并运行的完整SQL.我不知道是不是cmd.如果可能将完整字符串存储在状态字段或类似内容中,则Prepare()方法在这种情况下可能不会有用.


更新2:

根据下面的答案(和引用),表明在准备或执行过程中没有内部生成完整的SQL字符串,我做了一些使用.NET Reflector.即使是内部连接类似乎也会传递对象而不是将它们归结为字符串,例如:

内部抽象void AddPreparedCommand(SqlCommand cmd);
声明类型:System.Data.SqlClient.SqlInternalConnection
程序集:System.Data,Version = 2.0.0.0


总的来说,感谢每个人的细节水平,以证明可以做什么,并展示实际发生的事情.非常感激.我喜欢彻底的解释; 他们增加了保证,并为答案提供了信任.

Jes*_*mos 7

一个简单的循环用它们的值替换所有参数名称将为您提供类似于最终结果的东西,但是有几个问题.

  1. 由于SQL从未使用参数值实际重建,因此不需要考虑换行和引号等内容
  2. 注释中的参数名称从不实际处理其值,而是保持原样

有了这些,并考虑到以相同字符开头的参数名称,比如@NAME@NAME_FULL,我们可以用所有参数替换所有参数名称:

string query = cmd.CommandText;
foreach (SqlParameter p in cmd.Parameters.OrderByDescending(p => p.ParameterName.Length))
{
    query = query.Replace(p.ParameterName, p.Value.ToString());
}
Run Code Online (Sandbox Code Playgroud)

但是,这还有一个问题,那就是如果参数是一个字符串,那么SQL最初看起来像这样:

SELECT * FROM yourtable WHERE table_code = @CODE
Run Code Online (Sandbox Code Playgroud)

将如下所示:

SELECT * FROM yourtable WHERE table_code = SOME CODE WITH SPACES
Run Code Online (Sandbox Code Playgroud)

这显然不是合法的SQL,所以我们也需要考虑一些参数类型:

DbType[] quotedParameterTypes = new DbType[] {
    DbType.AnsiString, DbType.Date,
    DbType.DateTime, DbType.Guid, DbType.String,
    DbType.AnsiStringFixedLength, DbType.StringFixedLength
};
string query = cmd.CommandText;

var arrParams = new SqlParameter[cmd.Parameters.Count];
cmd.Parameters.CopyTo(arrParams, 0);

foreach (SqlParameter p in arrParams.OrderByDescending(p => p.ParameterName.Length))
{
    string value = p.Value.ToString();
    if (quotedParameterTypes.Contains(p.DbType))
        value = "'" + value + "'";
    query = query.Replace(p.ParameterName, value);
}
Run Code Online (Sandbox Code Playgroud)

  • 它应该足够好用于调试目的或任何需要的东西...... (3认同)
  • -1.这与发送到服务器的内容不同,无论如何都会导致无效的SQL. (2认同)

DOK*_*DOK 6

这里有几个类似的问题.

这个问题提供了最引人注目的答案:如何从SqlCommand-Object获取生成的SQL-Statment?

答案是:

你不能,因为它不会生成任何SQL.

参数化查询(CommandText中的查询)作为预准备语句的等效项发送到SQL Server.执行命令时,将分别处理参数和查询文本.在任何时候都不会生成完整的SQL字符串.

您可以使用SQL事件探查器来了解幕后.