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之前会打开事务。

关于这出错的任何想法?

编辑:我在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用于上面的示例代码。

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

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

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

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

  • 确保在重复调用ExecuteNonQuery时重用相同的MySqlCommand对象 。 小心你如何using – 你不想过早处置MySqlCommand对象。
  • 仅在每次新执行之前分配新参数值 – 不要更改语句文本或添加/删除参数。
  • 您可能还需要在所有时间内保持MySqlConnection活动状态。 这里也要小心using

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

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

我是从这里来的:

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标志。