从.NET中,我是否可以获取由SqlCommand对象(带有SQL参数)生成的完整SQL字符串?

10 浏览
0 Comments

从.NET中,我是否可以获取由SqlCommand对象(带有SQL参数)生成的完整SQL字符串?

在.NET环境下,我能否访问由 SqlCommand 对象生成的完整SQL字符串?

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

如果必须,我愿意使用反射技术。我相信这里有人知道如何访问它。


更新1:

我正在调用具有参数的存储过程 cmd.CommandType = CommandType.StoredProcedure ,并尝试获取生成和运行的完整SQL。

我想知道如果cmd. Prepare() 方法在此情况下是否有用,如果它可以将完整字符串存储在状态字段或类似的内容中。


更新2:

鉴于下面(和引用)的答案表明在准备或执行期间没有生成完整的SQL字符串,我使用.NET反编译器进行了一些探索。即使是内部连接类似乎也传递对象,而不是将它们化作字符串,例如:

internal abstract void AddPreparedCommand(SqlCommand cmd);

声明类型:System.Data.SqlClient.SqlInternalConnection

程序集:System.Data,版本=2.0.0.0


总的来说,感谢每个人提供的详细信息,证明了可以做什么,并展示了实际发生的事情。非常感谢。我喜欢详细的解释;它们增加了可靠性并给答案增加了可信度。

admin 更改状态以发布 2023年5月24日
0
0 Comments

这里已经有一些类似的问题了。

最有说服力的答案是回答了这个问题:如何从SqlCommand对象中获取生成的SQL语句?

答案是:

你不能获取,因为它并不会生成任何SQL语句。

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

你可以使用SQL Profiler来查看背后的情况。

0
0 Comments

一项简单的循环操作将所有参数名称替换为其值,将提供类似于最终结果的内容,但是存在几个问题:\n

    \n

  1. 由于SQL实际上从未使用参数值重建,因此无需考虑换行符和引号等内容。
  2. \n

  3. 注释中的参数名称实际上从未被处理其值,而是保留不变。
  4. \n

\n有了这些,再考虑以相同字符开头的参数名称,例如@NAME@NAME_FULL,我们可以使用该参数的值替换所有参数名称,该值将处于该参数的位置:\n

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

\n然而,这里还有一个问题,即如果一个参数是字符串,那么最初的SQL将如下所示:\n

SELECT * FROM yourtable WHERE table_code = @CODE

\n将会变为:\n

SELECT * FROM yourtable WHERE table_code = SOME CODE WITH SPACES

\n这显然不是合法的SQL,因此我们还需要考虑某些参数类型:\n

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);
}

0