我正在尝试使用预准备语句,而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。
答案 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
。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标志。