roadmaster roadmaster - 4 months ago 23
MySQL Question

MySql "SET @variable" throwing Fatal Error in C# code

I am getting a Fatal Error on using a ExecuteNonQuery().
I'm new to working with sql and as such im not sure why this

SET
command is causing a problem.

I'm using MySql 5.5.17, and I'm using C# .Net Framework 3.5 in the VS2010 IDE.

Exception Message = Fatal error encountered during command execution.
The Error Line = SET @oldguid = 250006;

the content from the sql file im using is as follows minus the "comments" that i removed:

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;


the
guid
column is a unsigned int(10)

the C# code I am using to process this .sql file is as follows:

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;
}
}


Can anyone see a problem with my code? Is there some special manipulation of the "SET @var" string that I need to do?

Any Help is appreciated
Thanks in advance

roadmaster


  • Edit * as a side note i should point out that if i use a sql management program like SQLYog it processes the same sql file with no problem so im assuming that the problem is somewhere in the manipulation of the string in my C# code.


Answer

Actually, I don't think that you can pass this line SET @oldguid = 250006; into a mysqlcommand object (actually I don't know). What you should do is have your program put these values in a local variable, and then replace the parameter in your update queries.

Find a way to mix your code and this one:

        // 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
            // ...
        }

And here is the extension method 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;
        }

Please give it a try and give feedback. Greetings

Comments