Способ увидеть запрос после применения параметров?

В приложении C # я создаю запрос, создавая строку запроса с параметрами, а затем добавляя параметры и их значения к команде. Например:

string query = "UPDATE USERS u SET u.username = @PARM_USERNAME " +
               "WHERE u.id = @PARM_USERID ";

command.Parameters.AddWithValue("@PARM_USERNAME", user.username);
command.Parameters.AddWithValue("@PARM_USERID", user.id);

command.Connection.Open();
int res = command.ExecuteNonQuery();

Было бы полезно увидеть запрос с примененными параметрами, возможно ли это в C # / Visual Studio? Я могу проверить команду.CommandText, но она показывает мне только то же содержимое, что и запрос выше, с заполнителями параметров. Если это помогает, это против MySQL.


person Mike    schedule 14.10.2011    source источник


Ответы (8)


Нет никакой гарантии, что существует такая вещь, как «запрос с примененными параметрами». Я бы надеюсь, что драйвер просто отправит команду в виде SQL и параметры в соответствующей форме для представления каждого значения. Зачем беспокоиться об экранировании значений и т. Д. Только для того, чтобы обработчик запросов отключил их и проанализировал на другой стороне? Более эффективно и менее рискованно просто передавать данные в двоичном формате с некоторым описанием.

Вы должны рассматривать это как некоторый код (SQL), который использует некоторые данные (параметры), и держать эти две концепции совершенно разными в вашем уме. Если вам нужно регистрировать, что происходит, я бы зарегистрировал это как параметризованный SQL и значения параметров отдельно.

person Jon Skeet    schedule 14.10.2011
comment
Ах, хорошо, я не знал об этом. Я думал, что параметры и значения были объединены в библиотеке MySQL перед отправкой на сервер, урок усвоен. - person Mike; 14.10.2011
comment
@Mike: Это возможно, но определенно не необходимо, и лично я надеюсь, что это не так :) - person Jon Skeet; 15.10.2011

Если вы хотите увидеть запрос с примененными параметрами:

string tmp = command.CommandText.ToString();
foreach (SqlParameter p in cmd.Parameters) {
    tmp = tmp.Replace('@' + p.ParameterName.ToString(),"'" + p.Value.ToString() + "'");
}

tmp будет удерживать запрос с примененными параметрами. Каждый параметр будет заключен в одинарные кавычки.

Конечно, выполнять это НЕ безопасно. Использую для отладки.

person Christopher Thomas Nicodemus    schedule 14.04.2014
comment
Для MS SQL иерархия наследования классов SqlParameter - System.Data.SqlClient.SqlParameter. Для MySQL это будет MySql.Data.MySqlClient.MySqlParameter. - person PeterCo; 27.05.2014
comment
Если вы сделаете .AddWithValue (@ P1, ...), тогда ParameterName уже начинается с '@', поэтому приведенный выше код пытается заменить @@ P1 значением, поэтому он не работает. Что мне не хватает? - person codah; 10.08.2017
comment
Я знаю, что это устарело, но в вашем коде есть проблемы. Прежде всего, вы используете command в первой строке и cmd в остальных. Они должны быть такими же. Во-вторых, нет необходимости вызывать ToString() на CommandText. Это уже строка. Далее, параметр следует заключать в кавычки, только если это котируемое значение. Например, целые числа - нет. И, наконец, как уже указывалось, вы не должны добавлять @ к имени параметра, поскольку обычно он уже есть. - person Jonathan Wood; 14.03.2018

Параметры остаются отдельными на всем пути к серверу, поэтому строка запроса, которую вы видите, - это то, что фактически идет на сервер, независимо от параметров. Поэтому я думаю, что вам нужно более непосредственно разбираться с пониманием того, как работают параметризованные запросы, а не пытаться увидеть, как запрос будет выглядеть с параметрами на месте. Вы можете использовать трассировку SQL, чтобы увидеть, как поступил запрос. Параметры по-прежнему будут отдельными, но они будут показывать вам значения.

Мой опыт работы с SQL Server, поэтому я не уверен, насколько это применимо к MySQL.

person BlueMonkMN    schedule 14.10.2011
comment
Спасибо за ваш ответ. Я не знал, что значения оставались отдельными на всем пути к серверу. - person Mike; 15.10.2011

Не уверен, зачем вам это нужно, но если это для целей отладки, вы всегда можете включить глобальный журнал на вашем локальном компьютере с базой данных mysql, чтобы увидеть запрос, отправленный в базу данных (хотя вы не хотите включать его на производственном компьютере, хотя - может значительно замедлить).

person krakover    schedule 14.10.2011
comment
Это для отладки, по сути, у меня есть запрос, который не дает того, что я ожидал. Я надеялся просто взять последний запрос из приложения и сверить его с БД, думаю, мне придется сделать это таким образом. Спасибо за ваш ответ. - person Mike; 14.10.2011

Если вы хотите использовать инструмент, вы можете попробовать использовать Toad для MySql. в котором есть профилировщик, и вы можете видеть, что отправляется на сервер.

person Hanlet Escaño    schedule 14.10.2011

ответ @christopher был отличным, но только строковые параметры потребуют ' (одинарная кавычка). лучше всего использовать метод ниже:

  private string getGeneratedSql(SqlCommand cmd)
    {
        string result = cmd.CommandText.ToString();
        foreach (SqlParameter p in cmd.Parameters)
        {
            string isQuted = (p.Value is string) ? "'" : "";
            result = result.Replace('@' + p.ParameterName.ToString(), isQuted + p.Value.ToString() + isQuted);
        }
        return result;
    }
person Amir Ziarati    schedule 30.11.2016

Я использую это для отладки в HTML. Должно быть достаточно времени для тестирования с простой копировальной пастой;


        public static string GetQueryHtml(string query, List<SqlParameter> parameters = null)
        {
            string _return = ""; string _parmStringValue; string _varlenght = "50";
            foreach (SqlParameter parameter in parameters)
            {
                if (parameter.SqlDbType == SqlDbType.DateTime)
                {
                    _parmStringValue = "'" + ((DateTime)parameter.Value).ToString("yyyy-MM-dd hh:mm:ss") + "'";
                    _return += Environment.NewLine +  "DECLARE " + parameter.ParameterName + " AS " + parameter.SqlDbType.ToString() + " SET " + parameter.ParameterName + " = " + _parmStringValue;
                }                 
                else if (parameter.SqlDbType == SqlDbType.NVarChar || parameter.SqlDbType == SqlDbType.Char)
                {
                    _varlenght = parameter.Value.ToString().Length.ToString();
                    _parmStringValue = "'" + parameter.Value.ToString() + "'";
                    _return += Environment.NewLine + "DECLARE " + parameter.ParameterName + " AS " + parameter.SqlDbType.ToString() + "(" + _varlenght + ") SET " + parameter.ParameterName + " = " + _parmStringValue;
                }
                else
                {
                    _return += Environment.NewLine + "DECLARE " + parameter.ParameterName + " AS " + parameter.SqlDbType.ToString() + " SET " + parameter.ParameterName + " = " + parameter.Value.ToString();
                }


            }

            return "<div><pre><code class='language-sql'>" + _return + Environment.NewLine + Environment.NewLine + query + "</code></pre></div>";

        }
person Rui Caramalho    schedule 23.07.2019

Для всех, кто хочет использовать ответ Кристофера с Mysql, это сработало для меня ...

string tmp = cmd.CommandText.ToString();
foreach (MySqlParameter param in cmd.Parameters)
{
    tmp = tmp.Replace(param.ParameterName.ToString(), "'" + param.Value.ToString() + "'");
}
person Danny    schedule 12.03.2021