2013-06-02 2 views
1

У меня есть DataGridView, который отображает список учеников и их информацию в таблице. Один столбец с именем «Оценка» доступен для редактирования, поэтому я хочу отразить все изменения в базе данных, когда пользователь нажимает кнопку «Сохранить изменения».C# MySQL, выполняющий UPDATE ничего не делает

Я написал этот код, но по какой-то причине он не работает:

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 содержит действительные данные.

Я проверил запрос MySQL в SQLyog и работал там, как должно

Это как если updateCommand.ExecuteNonQuery(); не выполняет.

EDIT: Я добавил несколько вещей, но он все еще не работает. Новый код

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 строку. Weird

EDIT3: Я выяснил, в чем проблема. База данных содержит хорватские буквы (čćšđž), поэтому, когда они находятся в команде, команда не выполняется. Я думаю, что это как-то связано с кодировкой символов. Когда команда содержит только обычные (ASCII) буквы, она работает нормально. Я не уверен, как это исправить, но по крайней мере сейчас я знаю, где находится проблема

EDIT4: Проблема решена. Изменено сопоставление базы данных с utf8

+0

Вы подтвердили, что sql работает вне программы? –

+0

Какой тип оценки. У вас есть потенциальная инъекция для инъекций sql. –

+0

Включите отладку и проверьте CommandText. Скорее всего, экспансия - это предложение where, которое не заполнено, и нет совпадений. –

ответ

1

Если у вас есть целые числа в типе базы данных, вам не нужно указывать одинарные кавычки для параметров. попробуйте без котировок одиночных чисел для типов номеров.

Вы можете избежать всех этих проблем и более безопасным способом является использование параметризованного запроса

EDIT

когда вы получаете значения строки вы можете получить его в зависимости от типа, как показано ниже

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"); 
+0

Я не заметил, что добавил одиночные кавычки. Я удалил их, но все равно не играл в кости. Я также немного изменил код, параметризуя команду, но она все еще не работает. – MrPlow

+0

В моем DataRow, похоже, нет метода «Поле». Может быть, потому, что я использую Net 2.0? Я как бы вынужден использовать его. – MrPlow

1

Этот код опасно хрупок. Поднимая некоторую связь и не будучи уверенным, что она даже открыта, это признак того, что вы не знаете, что происходит. Если вы даже не знаете, открыта ли связь, вы, вероятно, не знаете, занимается ли она транзакцией. Я согласен с акварагой - возможно, это так, но вы просто так запутались, что не можете сказать.В коде, который не фиксируется, может быть другая ошибка.

В любом случае я бы предложил ввести шаблон проектирования для централизации при открытии соединения, создать транзакцию, затем выполнить работу, затем выполнить или отменить. Выполнение этого в UI-событиях - довольно плохая практика, если не сказать больше. По крайней мере, попробуйте отделить свой пользовательский интерфейс от бизнеса и логики данных.

+0

Соединение 'if (connection.State == ConnectionState.Closed). Операция open();' бесполезна, поскольку она всегда закрыта, потому что я всегда закрываю ее. Я понятия не имею, почему я это написал. Это похоже на то, что я не доверял тому, что 'Close()' будет фактически выполняться в этом блоке finally (хотя я должен был использовать его в первую очередь). В любом случае я удалил это заявление из своего кода и просто оставил 'connection.Open()' там, и я на 100% уверен, что ничего не происходит, когда команда выполняется. Я новичок в C# и MySQL, поэтому я не знаю о них. – MrPlow

Смежные вопросы