从.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
总的来说,感谢每个人的细节水平,以证明可以做什么,并展示实际发生的事情.非常感激.我喜欢彻底的解释;他们增加了保证,并为答案提供了信任.
解决方法
一个简单的循环用它们的值替换所有参数名称将为您提供类似于最终结果的东西,但是有几个问题.
>由于sql实际上从未使用参数值进行重建,因此不需要考虑换行和引号等内容
>注释中的参数名称从不实际处理其值,而是保持原样
有了这些参数,并考虑了以相同字符开头的参数名称,如@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()); }
但是,还有一个问题,那就是如果参数是一个字符串,那么sql最初看起来像这样:
SELECT * FROM yourtable WHERE table_code = @CODE
将如下所示:
SELECT * FROM yourtable WHERE table_code = SOME CODE WITH SPACES
这显然不是合法的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); }