Заявление MySql готовит "не придерживаться"
Я пытаюсь использовать подготовленный оператор, и, хотя MySqlCommand выполняется просто отлично, время выполнения является ужасным. Мне пришлось написать результат cmd.IsPrepared на консоль, и, конечно же, это неверно. Здесь я настраиваю MySqlCommand:
MySqlCommand cmd = con.CreateCommand();
cmd.CommandText = @"INSERT INTO dict (pre, dist, dict.char, score) VALUES(@pre, @dist, @char, @score) ON DUPLICATE KEY UPDATE score = score + @score";
cmd.Parameters.Add("@pre", MySqlDbType.VarChar, 32);
cmd.Parameters.Add("@dist", MySqlDbType.Int32);
cmd.Parameters.Add("@char", MySqlDbType.VarChar, 1);
cmd.Parameters.Add("@score", MySqlDbType.Double);
cmd.Prepare();
Я также попытался выполнить Prepare() перед добавлением параметров с тем же результатом.
Затем у меня есть цикл кода, который выполняет некоторые вычисления и задает такие переменные:
cmd.Parameters[3].Value = score;
... и ничего не делает для команды, пока не придет время для запуска:
Console.WriteLine(cmd.IsPrepared);
cmd.ExecuteNonQuery();
Результат консоли всегда будет ложным. Все это делается в рамках основной транзакции, но это не похоже, что это должно испортить вещи. Однако я открываю транзакцию, прежде чем настраивать MySqlCommand.
Любые идеи относительно того, где это происходит неправильно?
edit: Я реплицировал код в java, и подготовленные операторы отлично работали в нем. Так что это не проблема с моим сервером базы данных, это, в частности, проблема в .net. Разумеется, разъем .net/не разбит для всех, так что может быть здесь сделка?
И он определенно не подготовлен и просто не устанавливает это значение bool, время работы в .net для некоторого тестового ввода так долго, что у меня нет терпения, чтобы ждать его, но в java выполняется тот же ввод через ~ 3 минуты. Оба используют в основном один и тот же код.
Вот простой тест, который я сделал в .net, так что вы можете увидеть полный код того, что я пытаюсь (я удалил UID и пароль из строки подключения, но в обычном коде они есть, соединение установлено, и оператор вводит данные в базу данных):
using (MySqlConnection con = new MySqlConnection(@"SERVER=localhost;DATABASE=rb;UID=;PASSWORD=;"))
{
con.Open();
using (MySqlCommand cmd = con.CreateCommand())
{
cmd.CommandText = @"INSERT INTO test (test.test) VALUES(?asdf)";
cmd.Prepare(); //doesn't work
cmd.Parameters.AddWithValue("?asdf", 1);
cmd.ExecuteNonQuery();
}
}
Я использую MySql.Data.dll версии 6.4.4.0 с версией времени выполнения v4.0.30319 в С# 2010. Я также включаю MySql.Data.MySqlClient для приведенного выше кода кода.
Ответы
Ответ 1
Похоже, вы делаете использование объекта MySqlCommand, по крайней мере, во втором примере. Чтобы получить какую-либо выгоду от подготовленных операторов, вам не нужно будет удалять объекты соединения и команды. Вы также захотите вызвать команду подготовки после установки CommandText и перед установкой любых параметров.
https://dev.mysql.com/doc/connector-net/en/connector-net-programming-prepared-preparing.html
Также подготовленные параметры оператора в MySQL не называются, они указаны на основе порядка. CommandText должен содержать только вопросительные знаки, где находятся параметры, и объекты параметров должны быть добавлены именно в этом порядке.
Ответ 2
Подготовка инструкции SQL, которая будет выполняться только один раз, не принесет каких-либо преимуществ по производительности, поэтому я предполагаю, что вы выполняете ее несколько раз:
- Убедитесь, что вы повторно используете тот же
MySqlCommand
объект, но не раз нажимаете ExecuteNonQuery
. Будьте осторожны с тем, как вы используете using
- вы не хотите слишком рано удалять объект MySqlCommand
.
- Назначать новые значения параметров перед каждым новым исполнением - не изменять текст оператора или добавлять/удалять параметры.
- Вам также может понадобиться поддерживать
MySqlConnection
в течение всего этого времени. Также будьте осторожны с using
.
BTW, некоторые поставщики ADO.NET вообще игнорируют метод Prepare
и "готовят" инструкцию только при первом выполнении (ODP.NET делает это, не уверен в MySQL). Если вы все сделали правильно, это не должно влиять на производительность...
Ответ 3
Попробуйте выполнить подготовку перед добавлением параметров.
Ответ 4
Я пришел сюда:
MySqlCommand Prepare() никогда не устанавливает IsPrepared в true
Это может быть ваша проблема - ваша строка подключения для .net должна иметь опцию "Игнорировать готовку" к false.
http://dev.mysql.com/doc/connector-net/en/connector-net-connection-options.html
Вздох. Этот плакат читает исходный код. Кажется, что многие другие не имеют этой проблемы (возможно, они уже знают о опции строки подключения?). Я не могу объяснить, почему это не в документации для "подготовить" или почему она отключена по умолчанию.. Ссылка на обсуждение:
http://grokbase.com/p/mysql/dotnet/0721kvem8t/prepared-statements
Жаль, что это не исправить мою проблему - просто подумал, что вы хотели бы знать. В итоге он позволил "подготовить" выполнить и включить флаг IsPrepared.