#c# #.net #mysql #parameterized
#c# #.net #mysql #параметризованный
Вопрос:
В приложении на 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.
Ответ №1:
Если вы хотите увидеть запрос с примененными параметрами:
string tmp = command.CommandText.ToString();
foreach (SqlParameter p in cmd.Parameters) {
tmp = tmp.Replace('@' p.ParameterName.ToString(),"'" p.Value.ToString() "'");
}
затем tmp будет удерживать запрос с примененными параметрами.
Каждый параметр будет заключен в одинарные кавычки.
Конечно, это НЕБЕЗОПАСНО для выполнения. Я использую его для целей отладки.
Комментарии:
1. Для MS SQL иерархией наследования класса ‘SqlParameter’ является System.Data.SqlClient.SqlParameter. Для MySQL это будет MySQL.Data.MySqlClient . MySqlParameter
2. Если вы это сделаете. AddWithValue(«@P1», …) тогда ParameterName уже начинается с «@», поэтому приведенный выше код пытается заменить «@@P1» значением, поэтому он не работает. Чего мне не хватает?
3. Я знаю, что это устарело, но в вашем коде есть проблемы. Прежде всего, вы используете
command
в первой строке иcmd
в других. Они должны быть одинаковыми. Во-вторых, нет необходимости вызыватьToString()
onCommandText
. Это уже строка. Далее, параметр должен быть заключен в кавычки, только если это заключаемое в кавычки значение. Например, целые числа не являются. И, наконец, как уже указывалось, вы не должны добавлять@
к имени параметра, поскольку оно обычно уже есть.
Ответ №2:
Нет никакой гарантии, что существует такая вещь, как «запрос с примененными параметрами». Я бы надеялся, что драйвер просто отправит команду как SQL и параметры в соответствующей форме для представления каждого значения. Зачем беспокоиться об экранировании значений и т. Д., Только для того, чтобы обработчик запросов не экранировал их и анализировал с другой стороны? Более эффективно и менее рискованно просто передавать данные в двоичном формате с некоторым описанием.
Вы должны рассматривать его как некоторый код (SQL), который использует некоторые данные (параметры), и держать эти два понятия в своем сознании очень раздельно. Если вам нужно записать, что происходит, я бы записал это как параметризованный SQL и значения параметров отдельно.
Комментарии:
1. Ах, хорошо, я не знал об этом. Я думал, что параметры и значения были объединены в библиотеке MySQL перед отправкой на сервер, урок усвоен.
2. @Mike: Возможно , что они есть, но, конечно, не обязательно , и лично я надеюсь, что это не так 🙂
Ответ №3:
Параметры остаются отдельными на всем пути до сервера, поэтому строка запроса, которую вы видите, — это то, что фактически отправляется на сервер, независимо от параметров. Поэтому я думаю, вам нужно более непосредственно разобраться с пониманием того, как работают параметризованные запросы, а не пытаться увидеть, как будет выглядеть запрос с установленными параметрами. Вы можете использовать SQL trace, чтобы увидеть поступление запроса. Параметры по-прежнему будут отдельными, но они будут показывать вам значения.
Мой опыт работы с SQL Server, поэтому я не уверен, насколько это применимо к MySQL.
Комментарии:
1. Спасибо за ваш ответ. Я не знал, что значения остаются отдельными на всем пути до сервера.
Ответ №4:
Не уверен, зачем вам это нужно, но если это для целей отладки, вы всегда можете включить глобальный журнал на вашем локальном компьютере с базой данных mysql, чтобы увидеть запрос, отправленный в базу данных (хотя вы не хотите включать его на рабочей машине — это может значительно замедлить его).
Комментарии:
1. Это для отладки, по сути, у меня есть запрос, который не приводит к тому, что я ожидаю. Я надеялся просто взять «окончательный» запрос из приложения и сверить его с базой данных, думаю, мне придется сделать это таким образом. Спасибо за ваш ответ.
Ответ №5:
Если вы хотите использовать инструмент, вы можете попробовать использовать Toad для MySQL, в котором есть профилировщик, и вы можете видеть, что отправляется на сервер.
Ответ №6:
ответ @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 resu<
}
Ответ №7:
Я использую это для отладки в 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>";
}
Ответ №8:
Для тех, кто хочет использовать ответ Кристофера с Mysql, это сработало для меня…
string tmp = cmd.CommandText.ToString();
foreach (MySqlParameter param in cmd.Parameters)
{
tmp = tmp.Replace(param.ParameterName.ToString(), "'" param.Value.ToString() "'");
}