【发布时间】:2009-08-10 13:37:26
【问题描述】:
我使用包含参数的 SQL 查询创建了一个 SqlCommand。 我将所有参数添加到类中。
有没有一种简单的方法可以在将生成的 SQL 查询发送到数据库之前查看它?
这对于调试目的很方便。 (例如,复制整个查询并在管理工作室中运行以尝试查明问题)
R
【问题讨论】:
标签: .net sql-server ado.net
我使用包含参数的 SQL 查询创建了一个 SqlCommand。 我将所有参数添加到类中。
有没有一种简单的方法可以在将生成的 SQL 查询发送到数据库之前查看它?
这对于调试目的很方便。 (例如,复制整个查询并在管理工作室中运行以尝试查明问题)
R
【问题讨论】:
标签: .net sql-server ado.net
不,因为实际上没有发生替换。查询按原样传递给服务器,参数单独传递。
但是,您可以编写一个方法来用实际参数值替换参数占位符...这就是我在我的一个应用程序中所做的,我会尽快发布代码。
这是我使用的代码,但它适用于 Oracle Lite 数据库,因此需要进行一些调整才能将其与另一个 RDBMS 一起使用。
public void Log(IDbCommand cmd)
{
StringBuilder sb = new StringBuilder(cmd.CommandText);
for (int i = 0; i < cmd.Parameters.Count; i++)
{
int pos = sb.ToString().IndexOf("?");
if (pos > 0)
sb.Replace("?", FormatParameter(cmd.Parameters[i]), pos, 1);
}
Log(sb.ToString());
}
private string FormatParameter(object prm)
{
IDbDataParameter p = prm as IDbDataParameter;
if (p.Value == null || p.Value == DBNull.Value)
return "NULL";
switch (p.DbType)
{
case DbType.AnsiString:
case DbType.AnsiStringFixedLength:
case DbType.String:
case DbType.StringFixedLength:
string s = p.Value as string;
return string.Format("'{0}'", s.Replace("'", "''"));
case DbType.Binary:
byte[] b = p.Value as byte[];
return HexString(b);
case DbType.Date:
case DbType.DateTime:
case DbType.DateTime2:
DateTime d = (DateTime)p.Value;
return string.Format("to_date('{0}', 'dd/mm/yyyy hh24:mi')", d.ToString("dd/MM/yyyy HH:mm"));
default:
return p.Value.ToString();
}
}
private string HexString(byte[] bytes)
{
StringBuilder sb = new StringBuilder();
for (int i=0; i < bytes.Length; i++)
sb.AppendFormat("{0:X2}", bytes[i]);
return sb.ToString();
}
【讨论】:
好吧,您可以在 SQL Profiler 中看到整个查询(诚然,这是在 它被发送到数据库之后),但它为您提供了一种复制粘贴语句的简单方法,以便您可以调试在 Management Studio 中使用。
只需添加一个新跟踪,运行执行数据库调用的代码,然后从生成的捕获事件中复制粘贴命令。
【讨论】:
我只是在发布之前重新阅读了您的问题。虽然这种技术可能无法直接应用于 .net,但您也许可以解决类似问题。所以:
我最近不得不在 T-SQL 中做很多动态编码,我想出了以下例程。假设你有一大段这样的代码:
DECLARE
@Command nvarchar(max)
,@SearchFor int
SET @Command = 'SELECT * from MyTable where PrimaryKey = @SearchFor'
SET @SearchFor = 1
EXECUTE sp_executesql
@Command
,N'@SearchFor int'
,@SearchFor
这当然非常简单——如果您需要编写动态代码,您将遇到复杂到极其复杂的查询,而且您发现这些查询可能非常难以调试。下面是我如何重写上面的代码:
DECLARE
@Command nvarchar(max)
,@SearchFor int
,@Debug int
-- 0 = Run it
-- 1 = Run and display it
-- 2 = Display it
SET @Command = 'SELECT * from MyTable where PrimaryKey = @SearchFor'
SET @SearchFor = 1
SET @Debug = 1
IF @Debug > 0
-- Show the command that would be run
PRINT replace(@Command, '@SearchFor', cast(@SearchFor as varchar(10)))
IF @Debug < 2
-- Run it
EXECUTE sp_executesql
@Command
,N'@SearchFor int'
,@SearchFor
这是编写和调试的额外代码,但一旦到位并开始工作,它在调试情况下就非常宝贵。如果它是存储过程的一部分,请将 @Debug 设为默认为 0 的参数,并确保如果设置为 2,则该过程实际上不会执行任何操作。
【讨论】: