【问题标题】:Is there a way to get the full sql text back from SqlCommand after param substitution?有没有办法在参数替换后从 SqlCommand 获取完整的 sql 文本?
【发布时间】:2009-08-10 13:37:26
【问题描述】:

我使用包含参数的 SQL 查询创建了一个 SqlCommand。 我将所有参数添加到类中。

有没有一种简单的方法可以在将生成的 SQL 查询发送到数据库之前查看它?

这对于调试目的很方便。 (例如,复制整个查询并在管理工作室中运行以尝试查明问题)

R

【问题讨论】:

    标签: .net sql-server ado.net


    【解决方案1】:

    不,因为实际上没有发生替换。查询按原样传递给服务器,参数单独传递。

    但是,您可以编写一个方法来用实际参数值替换参数占位符...这就是我在我的一个应用程序中所做的,我会尽快发布代码。


    这是我使用的代码,但它适用于 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();
        }
    

    【讨论】:

      【解决方案2】:

      好吧,您可以在 SQL Profiler 中看到整个查询(诚然,这是在 它被发送到数据库之后),但它为您提供了一种复制粘贴语句的简单方法,以便您可以调试在 Management Studio 中使用。

      只需添加一个新跟踪,运行执行数据库调用的代码,然后从生成的捕获事件中复制粘贴命令。

      【讨论】:

      • SQL Profiler 是您的朋友。
      • 即使我对数据库的访问仅限于连接字符串,这是否有效?还是我需要更多访问权限才能运行可以跟踪的分析器?
      • 您使用的凭据是否具有系统管理员权限?如果不是,那么你可能是 SOL。那么,托马斯的代码可能是你最好的选择。
      【解决方案3】:

      我只是在发布之前重新阅读了您的问题。虽然这种技术可能无法直接应用于 .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,则该过程实际上不会执行任何操作。

      【讨论】:

      • 我可以理解,额外的一点点努力显然会给调试部门带来很多好处。我可能必须创建类似的东西(如果没有这样的东西)。
      猜你喜欢
      • 2020-11-14
      • 1970-01-01
      • 1970-01-01
      • 2011-07-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多