使用ExecuteNonQuery()时出现致命错误。
我是新手使用sql,因此我不确定为什么这个SET
命令导致了问题。
我正在使用MySql 5.5.17,而我在VS2010 IDE中使用C#.Net Framework 3.5。
异常消息=在命令执行期间遇到致命错误。 错误行= SET @oldguid = 250006;
我使用的sql文件中的内容如下,减去我删除的“评论”:
DELETE FROM `disables` WHERE `sourceType`=0 AND `entry`=61904;
INSERT INTO `disables` (`sourceType`, `entry`, `flags`, `comment`) VALUES(0, 61904, 8, 'Magma Totem TEST - can crash client by spawning too many totems');
SET @oldguid = 250006;
SET @newguid = 202602;
UPDATE `creature` SET `guid`=@newguid WHERE `guid`=@oldguid;
UPDATE `creature_addon` SET `guid`=@newguid, `path_id`=@newguid*100 WHERE `guid`=@oldguid;
UPDATE `waypoint_data` SET `id`=@newguid*100 WHERE `id`=@oldguid*100;
UPDATE `areatrigger_teleport` SET `target_orientation`=2.255664 WHERE `id`=4386;
UPDATE `gameobject` SET `spawnMask`=3 WHERE `guid`=22674;
guid
列是unsigned int(10)
我用来处理这个.sql文件的C#代码如下:
filename = lstBox_SqlFiles.SelectedItem.ToString();
mysql = new MySqlConnection(connection + Database);
string line;
OpenDatabase();
using (StreamReader reader = new StreamReader(filename))
{
StringBuilder parsedLine = new StringBuilder();
int count = 0;
while ((line = reader.ReadLine()) != null)
{
if (line.Length > 0 && !line.StartsWith("--"))
{
if (line.EndsWith(";"))
{
if (parsedLine.Length > 0)
line = parsedLine.ToString() + line;
try
{
count++;
lbl_LineQuery.Text = line;
lbl_QueryCount.Text = String.Format("Count: {0}", count);
MySqlCommand cmd = new MySqlCommand(line, mysql);
cmd.ExecuteNonQuery();
}
catch (MySqlException ex)
{
string msg = String.Format("Source FileName: SqlUpdater.cs\nSql FileName: {0}\nError Line: {1}\nException Message: {2}\n", filename, line, ex.Message);
MessageBox.Show("cmd.ExecuteNonQuery() Error!\n" + msg, "MySql Error", MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1);
return;
}
sbClear(parsedLine);
}
else
{
parsedLine.Append(line);
continue;
}
}
else
continue;
}
}
有人能看到我的代码有问题吗?我需要对“SET @var”字符串进行一些特殊操作吗?
感谢任何帮助 提前致谢
路线大师
答案 0 :(得分:5)
这是我将MySql.Data.dll从1.0升级到6.9时发现的问题。例如:
MYSQL:
SET @foo = 'foo'
消息: 命令执行期间遇到致命错误。
我怀疑MySql.Data试图将@foo作为预备语句变量进行插入,并希望我填充它。关于死亡的痛苦。因此,解决方案似乎是告诉MySql.Data这是一个文字“@”而不是一个标记。
可能还有其他方法,但我找到的实用解决方案是引用后引号中的变量名称:
SET @`foo` = 'foo'
SELECT @`foo`
我希望这会有所帮助。
答案 1 :(得分:2)
实际上,我认为您不能将此行SET @oldguid = 250006;
传递给mysqlcommand对象(实际上我不知道)。你应该做的是让你的程序将这些值放在局部变量中,然后替换更新查询中的参数。
找到一种混合代码的方法:
// This line should be outside the While loop
Dictionary<string, string> variables = new Dictionary<string, string>();
if (line.Trim().ToUpper().StartsWith("SET"))
{
List<string> commandLine;
commandLine = line.Trim(' ',';').Split().Distinct().ToList();
commandLine.Remove(string.Empty);
// After next line, the 'variables' dictionary contains the name
// of the variable you want to set, and its value
variables[commandLine[1]] = commandLine[3];
// ...
// Do something here (try catch, chatever, but NO MySqlCommand)
// ...
}
else
{
// If the line contains any of the variables you previously set,
// i will be the index of this variable, -1 otherwise
int i = line.ContainsAnyOfAt(variables.Keys);
while(i>=0)
{
// Here we replace the parameter by its value, for example:
// UPDATE `creature` SET `guid`=@newguid WHERE `guid`=@oldguid;
// becomes (after all loops):
// UPDATE `creature` SET `guid`=202602 WHERE `guid`=250006;
line = line.Replace(variables.Keys.ElementAt(i), variables.Values.ElementAt(i));
i = line.ContainsAnyOfAt(variables.Keys,i+1);
}
// ...
// This is where you should put the code of MySqlCommand
// ...
}
这是扩展方法ContainsAnyOfAt:
public static int ContainsAnyOfAt<T>(this global::System.String source, IEnumerable<T> values, int startIndex = 0)
{
if (source == null) throw new ArgumentNullException("source");
for (int i = startIndex ; i < values.Count(); i++)
{
if (source.Contains(values.ElementAt(i).ToString()))
{
return i;
}
}
return -1;
}
请试一试并提供反馈。 问候
答案 2 :(得分:2)
代码基本上是这样的:
MySqlCommand
(从而创建自己的范围!)@oldguid
。如果您希望能够使用变量,请使用一个MySqlCommand对象,并调用ExecNonQuery()
一次。
您最好的选择是创建存储过程。也许你的“guid”/整数值需要2个参数。
它在SQLYog中工作的原因是所有这些语句都在相同的上下文中运行,而不是在不同的会话中运行。
答案 3 :(得分:2)
Андрей的建议对我有用。
我的MySQL数据库中有一个相当复杂的过程,我不希望将其包含在我的C#代码中。我是这样做的:
//Open connection
string conString = "server=myserver; Uid=myusername; database=myscheme; Pwd=mypwd";
MySqlConnection con = new MySqlConnection(conString);
try
{
//Set first variable, @START
string sql = "SET @START = '" + date1 + "'";
MySqlScript cmd = new MySqlScript(con, sql);
cmd.Connection.Open();
cmd.Execute();
//Set second variable, @END
sql = "SET @END = '" + date2 + "'";
cmd = new MySqlScript(con, sql);
cmd.Execute();
//Send procedure call
MySqlDataAdapter MyDA = new MySqlDataAdapter();
sql = "call MY_DB_PROCEDURE";
MyDA.SelectCommand = new MySqlCommand(sql, con);
//From here you can process the DB response as you want
//For instance, display the results in a datagridview
DataTable table = new DataTable();
MyDA.Fill(table);
BindingSource bSource = new BindingSource();
bSource.DataSource = table;
//"dataGridView1" is already placed in the active form
dataGridView1.DataSource = bSource;
dataGridView1.Visible = true;
}
catch (Exception e)
{
//Error handling procedure
}
finally
{
if (con.State == ConnectionState.Open)
{
con.Dispose(); // return connection to the pool
}
}
更优雅的解决方案是在连接字符串中添加“Allow User Variables = True”。 示例如下:
//Open connection
string conString = "server=myserver; Uid=myusername; database=myscheme; Pwd=mypwd; Allow User Variables=True";
MySqlConnection con = new MySqlConnection(conString);
try
{
//Open connection
con.Open();
//Set first variable, @START
//Set second variable, @END
//Send procedure call
string sql = "SET @START = '" + date1 + "';" +
"SET @END = '" + date2 + "';" +
"CALL MY_DB_PROCEDURE";
MySqlDataAdapter MyDA = new MySqlDataAdapter();
MyDA.SelectCommand = new MySqlCommand(sql, con);
//From here you can process the DB response as you like
//...
}
catch (Exception e)
{
//Error handling procedure
}
finally
{
if (con.State == ConnectionState.Open)
{
con.Dispose(); // return connection to the pool
}
}
答案 4 :(得分:2)
添加
;Allow User Variables=True
到连接字符串。
答案 5 :(得分:1)
编写包含变量的程序(@ name_var)。抛出异常。帮助改变类MySqlCommand类MySqlScript
答案 6 :(得分:-1)
添加连接字符串;允许用户变量=真