执行UPDATE的C#MySQL什么都不做

时间:2013-06-02 12:00:18

标签: c# mysql

我有一个DataGridView,它在表格中显示学生及其信息的列表。 一个名为“Grade”的列是可编辑的,因此我希望在用户单击“Save Changes”按钮时反映对数据库的所有更改。

我写过这段代码,但由于某些原因它不起作用:

    private void bttnStudentsSaveChanges_Click(object sender, EventArgs e)
    {
        try
        {
            if (connection.State == ConnectionState.Closed) connection.Open();
            DataTable changes = ((DataView)dataGridViewStudents.DataSource).Table.GetChanges();
            if (changes != null)
            {
                foreach (DataRow row in changes.Rows)
                {
                    MySqlCommand updateCommand = connection.CreateCommand();
                    updateCommand.CommandText = @"UPDATE grades
                                            INNER JOIN lectures ON grades.idLecture = lectures.id
                                            INNER JOIN students ON grades.idStudent = students.id
                                            SET grades.grade = '" + row["Grade"] + @"'
                                            WHERE students.id = '" + row["ID"] +
                                                @"' AND (students.name = '" + row["Name"] +
                                                @"' AND students.surname = '" + row["Surname"] +
                                                "') AND lectures.name = '" + row["Lecture"] + "'";
                    updateCommand.ExecuteNonQuery();
                }
            }  
        }
        catch (System.Exception ex)
        {
            MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            return;
        }
    }

执行此操作时,不会对数据库进行任何更改 因为我必须连接多个表,所以我不能使用MySqlCommandBuilder(至少我认为这是我尝试过它并且得到错误的原因)所以我决定手动完成。

我已经设置了几个断点来检查数据是否正确,changes变量和CommandText属性都包含有效数据。

我已经在SQLyog中测试了MySQL查询,它应该在那里工作

好像updateCommand.ExecuteNonQuery();没有执行。

编辑:我添加了一些内容,但它仍无效。新代码是

    private void bttnStudentsSaveChanges_Click(object sender, EventArgs e)
    {
        try
        {
            connection.Open();
            DataTable changes = ((DataView)dataGridViewStudents.DataSource).Table.GetChanges();
            if (changes != null)
            {
                foreach (DataRow row in changes.Rows)
                {
                    MySqlCommand updateCommand = connection.CreateCommand();
                    updateCommand.CommandText = @"UPDATE grades
                                                INNER JOIN lectures ON grades.idLecture = lectures.id
                                                INNER JOIN students ON grades.IDStudent = students.ID
                                                SET grades.grade = @grade
                                                WHERE students.ID = @ID AND (students.name = @name AND students.surname = @surname) 
                                                AND lectures.name = @lecture";
                    updateCommand.Parameters.AddWithValue("@grade", row["Grade"]);
                    updateCommand.Parameters.AddWithValue("@ID", row["ID"]);
                    updateCommand.Parameters.AddWithValue("@name", row["Name"]);
                    updateCommand.Parameters.AddWithValue("@surname", row["Surname"]);
                    updateCommand.Parameters.AddWithValue("@lecture", row["Lecture"]);
                    updateCommand.ExecuteNonQuery();
                }
            }  
        }
        catch (System.Exception ex)
        {
            MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            return;
        }
        finally
        {
            if(connection.State == ConnectionState.Open) connection.Close();
        }
    }

EDIT2:我发现ExecuteNonQuery会返回一些受影响的行。结果我得到0。这是奇怪的,因为在SQLyog中执行命令会导致1行受到影响。怪异

EDIT3:我发现了问题所在。该数据库包含克罗地亚字母(čćšđž),因此当它们处于命令中时,命令不会执行。我认为这与字符编码有关。当命令只包含常规(ASCII)字母时,它会正常工作。我不知道如何修复它,但至少现在我知道问题在哪里

EDIT4:问题已解决。将数据库排序规则更改为utf8

2 个答案:

答案 0 :(得分:1)

如果数据库类型中有整数,则不需要为参数指定单引号。 尝试没有数字类型的单打引号。

您可以使用参数化查询

来避免所有这些问题,更安全的方法

修改

当你获得行值时,你可以根据类型获得它,如下所示

row.Field<int>("ID")

更改您的代码,如下所示,再次检查类型

updateCommand.Parameters.AddWithValue("@grade",  row.Field<int>("Grade"));
updateCommand.Parameters.AddWithValue("@ID",  row.Field<int>("ID"));
updateCommand.Parameters.AddWithValue("@name",  row.Field<string>("Name"));
updateCommand.Parameters.AddWithValue("@surname",  row.Field<string>("Surname"));
updateCommand.Parameters.AddWithValue("@lecture",  row.Field<string>("Lecture");

答案 1 :(得分:1)

此代码非常脆弱。拿起一些连接而不确定它是否打开是不明白发生了什么的迹象。如果您甚至不知道您是否打开了连接,那么您可能不知道它是否参与了交易。我同意aquaraga - 它可能只是你纠缠不清你无法分辨。在代码中的其他地方可能存在另一个不提交的错误。

在任何情况下,我建议在打开连接时引入设计模式进行集中,创建事务然后执行工作然后提交或回滚。至少可以说,在UI事件中执行它是一个非常糟糕的做法。至少尝试将UI与业务和数据逻辑分开。