MySql语句准备“不坚持”

问题描述 投票:10回答:4

我正在尝试使用预准备语句,而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之前会打开事务。

关于这出错的任何想法?

编辑:我在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();
            }
        }

我在c#2010中使用MySql.Data.dll版本6.4.4.0和v4.0.30319的运行时版本。我还包括MySql.Data.MySqlClient用于上面的示例代码。

c# mysql
4个回答
7
投票

看起来你正在使用MySqlCommand对象,至少在你的第二个例子中。要获得预准备语句的任何好处,您需要不处置连接和命令对象。您还需要在设置CommandText之后和设置任何参数之前调用prepare。

https://dev.mysql.com/doc/connector-net/en/connector-net-programming-prepared-preparing.html

MySQL中也准备好的语句参数没有命名,它们是根据顺序指定的。 CommandText应该只包含参数所在的问号,并且参数对象需要按照该顺序添加。


2
投票

准备一个只执行一次的SQL语句不会带来任何性能上的好处,所以我假设你多次执行它:

  • 确保在重复调用MySqlCommand时重复使用相同的ExecuteNonQuery对象。小心你如何使用using - 你不想太早处理MySqlCommand对象。
  • 仅在每次新执行之前分配新参数值 - 不要更改语句文本或添加/删除参数。
  • 在这段时间里你也可能需要让MySqlConnection保持活力。这里也要小心using

顺便说一下,一些ADO.NET提供者完全忽略了Prepare方法,并且仅在第一次执行时“准备”语句(ODP.NET就是这样,不确定MySQL)。如果你做的一切都正确,这应该对性能没有任何影响......


1
投票

在添加参数之前尝试运行准备。


1
投票

我是从这里来的:

MySqlCommand Prepare() never sets IsPrepared to 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标志。

© www.soinside.com 2019 - 2024. All rights reserved.