MySql语句准备“不坚持”

时间:2011-10-23 15:02:32

标签: c# 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();

控制台的结果始终为false。这一切都是在一个基本的交易中完成的,但这似乎不应该搞砸了。不过,我确实在设置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。

4 个答案:

答案 0 :(得分:7)

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

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

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

答案 1 :(得分:2)

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

  • 确保在重复调用MySqlCommand时重复使用相同的ExecuteNonQuery对象。请谨慎使用using - 您不希望过早处置MySqlCommand对象。
  • 仅在每次新执行之前分配新参数值 - 不要更改语句文本或添加/删除参数。
  • 您可能还需要在所有时间内保持MySqlConnection活着。这里也要注意using
BTW,一些ADO.NET提供者完全忽略Prepare方法并且只在第一次执行时“准备”该语句(ODP.NET这样做,不确定MySQL)。如果你做的一切都正确,这应该对性能没有任何影响......

答案 2 :(得分:1)

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

答案 3 :(得分: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标志。