VB.NET: Обновление базы данных MySQL из (CheckedListBox-ComboBox)

Я сделал форму, которая должна получить данные о посещаемости для определенного сеанса. Используемые элементы:

1- CheckedListBox

2- Combobox: CB_Students

3- кнопка: обновить

Моя таблица Студент, которая содержит код | Имя | Фамилия | Day1| Day2| Day3| Day4| День 5, где Дни имеют тип tinyint, ссылаясь на Присутствие или Отсутствие.

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

Поскольку CheckedListBox косвенно создается записями базы данных, я полагаю, что не могу напрямую подключить его к базе данных, поэтому я создал скрытый ComboBox со значениями Code, соответствующими каждому ученику, показанному в CheckedListBox.

Например, моя таблица учеников выглядит так:

Код | F_Name | L_Name

1 | F1 | L1

2 | F2 | L2

CheckedListBox содержит: F1 L1 и F2 L2, а ComboBox содержит 1 и 2.

Номер дня также находится во время загрузки формы и сохраняется как открытая переменная Inquiry.

Ниже мой код для кнопки обновления:

Dim j, S As Integer
    sqlstr = "UPDATE Student SET Day'" & Inquiry & "'=@field1 WHERE Code='" & CB_Students.Items.Item(j) & "'"
    DBCmd = New MySql.Data.MySqlClient.MySqlCommand(sqlstr, DBConn)
    With DBCmd
        For j = 0 To CheckedListBox1.Items.Count - 1
            S = CheckedListBox1.GetItemCheckState(j)
            If S = 1 Then
                .Parameters.AddWithValue("@field1", 1)
            ElseIf S = 0 Then
                .Parameters.AddWithValue("@field1", 0)
            End If
        Next j
    End With
    DBCmd.ExecuteNonQuery()
    DBCmd.Dispose()

Однако во время выполнения я получаю сообщение об ошибке: "Параметр @field1 уже определен".

Как мне справиться с этой проблемой? Кроме того, правильно ли используется оператор CB_Students.Items.Item(j), чтобы дать моей строке sql код студента в ComboBox?

Обновление 1:

Запрос - это целое число. Я также попробовал следующий код:

 For j = 0 To CheckedListBox1.Items.Count - 1
        S = CheckedListBox1.GetItemCheckState(j)
        If S = 1 Then
            With DBCmd
                .Parameters.AddWithValue("@field1", 1)
                .ExecuteNonQuery()
                .Dispose()
            End With
        ElseIf S = 0 Then
            With DBCmd
                .Parameters.AddWithValue("@field1", 0)
                .ExecuteNonQuery()
                .Dispose()
            End With
        End If
    Next j

Но опять же, как и в моем ответе на Never_Mind, я получаю следующую ошибку в первой строке DBCmd.ExecuteNonQuery(): "У вас есть ошибка в вашем синтаксисе SQL; проверьте правильность синтаксиса в руководстве, соответствующем вашей версии сервера MySQL для используйте рядом с ''4' =1 WHERE Code='6'' в строке 1".

Значения кажутся правильными. Номер дня - 4, поле 1 - 1, код - 6. Я не вижу, в чем проблема.

Обновление 2:

Ниже приведен код для заполнения CheckedListBox и ComboBox, который находится в форме загрузки. C_Code - это код класса, еще одно поле в таблице учеников. ClassID - это открытая целочисленная переменная, сохраненная в предыдущей форме. Эта форма отображается с использованием метода.ShowDialog.

sqlstr = "SELECT * FROM Student WHERE C_Code = '" & ClassID & "'"
DBCmd = New MySql.Data.MySqlClient.MySqlCommand(sqlstr, DBConn)
DBDR = DBCmd.ExecuteReader
    While (DBDR.Read())
        Std_Name = DBDR("F_Name") & " " & DBDR("L_Name")
        CheckedListBox1.Items.Add(Std_Name)
        CB_Students.Items.Add(DBDR("Code"))
    End While
    DBCmd.Dispose()
    DBDR.Close()

Кроме того, код является целым числом.

Обновление 3:

Я изменил тип запроса в String и удалил одинарные кавычки.

Во всяком случае, я думал, может быть, я мог бы сделать разные номера полей. Что-то вроде этого:

Dim j, S, k As Integer
    sqlstr = "UPDATE Student SET D" & Inquiry & " =@field" & k & " WHERE Code='" & CB_Students.Items.Item(j) & "' "
DBCmd = New MySql.Data.MySqlClient.MySqlCommand(sqlstr, DBConn)
For j = 0 To CheckedListBox1.Items.Count - 1
        For k = 1 To CheckedListBox1.Items.Count
            S = CheckedListBox1.GetItemCheckState(j)
            If S = 1 Then
                With DBCmd
                    .Parameters.AddWithValue("@field" & k, 1)
                    .ExecuteNonQuery()
                    .Dispose()
                End With
            ElseIf S = 0 Then
                With DBCmd
                    .Parameters.AddWithValue("@field" & k, 0)
                    .ExecuteNonQuery()
                    .Dispose()
                End With
            End If
        Next k
    Next j

Но это не работает. Я думаю, должно быть что-то не так с тем, как я объединил @field и k при добавлении через команду. Как я могу заставить его работать?

Буду очень признателен за помощь!

3 ответа

Решение

Просто понял ответ. Поскольку мы не можем воссоздать @field1, мы воссоздаем строку sql (все это), помещая ее в цикл.

For j = 0 To CheckedListBox1.Items.Count - 1
        S = CheckedListBox1.GetItemCheckState(j)
        sqlstr = "UPDATE Student SET D" & Inquiry & " =@field1 WHERE Code='" & CB_Students.Items.Item(j) & "' "
        DBCmd = New MySql.Data.MySqlClient.MySqlCommand(sqlstr, DBConn)
            If S = 1 Then
                With DBCmd
                .Parameters.AddWithValue("@field1", 1)
                    .ExecuteNonQuery()
                    .Dispose()
                End With
            ElseIf S = 0 Then
                With DBCmd
                .Parameters.AddWithValue("@field1", 0)
                    .ExecuteNonQuery()
                    .Dispose()
                End With
            End If
    Next j

Этот был довольно жестким! Но, черт возьми, это легко, когда это решено, а?

Попробуй это

 With DBCmd
        For j = 0 To CheckedListBox1.Items.Count - 1
            S = CheckedListBox1.GetItemCheckState(j)
            If S = 1 Then
                .Parameters.AddWithValue("@field1", 1)
 .ExecuteNonQuery()
            ElseIf S = 0 Then
                .Parameters.AddWithValue("@field1", 0)
 .ExecuteNonQuery()
            End If
        Next

    End With

Сначала удалите одиночную кавычку из строки Inquiry, чтобы объединить прогрессив поля со словом день. ВНИМАНИЕ. Я полагаю, что вы имеете полный контроль над значением переменной Inquiry и проверяете, является ли она действительным числом, прежде чем объединять слово Day

Второй Определите ваш параметр только один раз за пределами цикла с фиктивным значением, затем внутри цикла установите значение в состояние текущего элемента и выполните запрос

Третье Использование параметра также для значения кода

j = 0 ' you should initialize this variable to a valid index inside the items collection of the combo'
sqlstr = "UPDATE Student SET Day" & Inquiry & "=@field1 WHERE Code=@code"
DBCmd = New MySql.Data.MySqlClient.MySqlCommand(sqlstr, DBConn)
With DBCmd
    .Parameters.AddWithValue("@field1", 0)
    .Parameters.AddWithValue("@code", Convert.ToInt32(CB_Students.Items(j)))
    For j = 0 To CheckedListBox1.Items.Count - 1
        S = if(CheckedListBox1.GetItemCheckState(j) = CheckState.Checked, 1, 0)
       .Parameters("@field1").Value = S
       .ExecuteNonQuery()
    Next j
End With

Этот подход не очень эффективен, потому что команда обновления выполняется для каждого элемента дня (проверено или нет), но для устранения этой неэффективности потребуется полное переписывание этого кода.

Что касается использования элементов комбинированного списка, я думаю, что вы должны использовать свойство SelectedValue, но это зависит от того, как вы заполнили комбо и какое значение присваивается свойству ValueMember и какой тип данных является code поле базы данных

Другие вопросы по тегам