Заявление 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.