Есть ли способ получить полный текст sql обратно из SqlCommand после подстановки параметров? - PullRequest
5 голосов
/ 10 августа 2009

Я создал SqlCommand с SQL-запросом, содержащим параметры. Затем я добавляю все параметры в класс.

Есть ли простой способ увидеть полученный SQL-запрос перед его отправкой в ​​базу данных?

Это было бы удобно для отладки. (например, скопировать весь запрос и запустить его в студии управления, чтобы попытаться определить проблемы)

R

Ответы [ 3 ]

4 голосов
/ 10 августа 2009

Нет, потому что на самом деле замены не происходит. Запрос передается на сервер как есть, а параметры передаются отдельно.

Однако вы можете написать метод для замены заполнителей параметров фактическими значениями параметров ... Это то, что я делал в одном из своих приложений, я опубликую код, как только смогу.


Вот код, который я использую, но он предназначен для базы данных Oracle Lite, поэтому для его использования с другой СУБД потребуется некоторая адаптация.

    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 голосов
/ 10 августа 2009

Ну, вы можете увидеть весь запрос в SQL Profiler (по общему признанию, это после , он был отправлен в базу данных), но он дает вам простой способ скопировать-вставить оператор, чтобы вы могли отладить с помощью что внутри Management Studio.

Просто добавьте новую трассировку, запустите код, который вызывает базу данных, затем скопируйте и вставьте команду из полученных событий захвата.

0 голосов
/ 10 августа 2009

Я просто перечитал ваш вопрос, прежде чем опубликовать это. Хотя эту технику, вероятно, нельзя напрямую применить к .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 процедура на самом деле ничего не делает.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...