Почему поле моей базы данных не обновляется? - PullRequest
0 голосов
/ 29 мая 2019

Я разрабатываю программу, которая позволяет пользователю сдавать тесты и получать за это оценку, процент и оценку.Они будут храниться в таблице данных с именем «tblStudentScores».Приведенный ниже код SQL предназначен для обновления соответствующей записи, когда пользователь завершает тест, чтобы сохранить его последнюю оценку за этот тест.

UPDATE tblStudentScores
SET Score = @Score, Percentage = @Perc, Grade = @Grade, CompletedTask = True
WHERE SpecificTaskID = @SpecID AND StudentID = @StudID;

При тестировании этого SQL в MS Access он работает отлично.Однако, когда я пытаюсь использовать тот же запрос, что и OleDBCommand в VB.NET, ничего не происходит.Нет сообщения об ошибке, но код также не обновляет таблицу.

Я думал, что это может быть связано с параметрами, поэтому я явно объявил их в верхней части запроса:

PARAMETERS @SpecID Number, @StudID Number, @Score Number, @Perc Number, @Grade Text;

Теперь, вместо того чтобы ничего не происходило, я получаю следующее сообщение об ошибке:

An unhandled exception of type 'System.Data.OleDb.OleDbException' occurred in System.Data.dll
Additional information: Cannot update 'Score'; field not updateable.

Как я уже говорил ранее, запрос выполнен в конструкторе запросов MS Access, поэтому поле должно быть обновляемым.Что может быть не так?

РЕДАКТИРОВАТЬ: После дальнейшего тестирования я обнаружил, что запрос работает в VB при использовании фиксированных входных данных, а не параметров.Таким образом, проблема явно связана с параметрами, но в чем может быть проблема?

РЕДАКТИРОВАТЬ: весь фрагмент кода, в котором я создаю и использую запрос ниже:

 Dim cmd As New OleDbCommand("PARAMETERS @Score Number, @Perc Number, @Grade Text, @SpecID Number, @StudID Number; UPDATE tblStudentScores " & _
                                    "SET Score = @Score, Percentage = @Perc, Grade = @Grade, CompletedTask = True " & _
                                    "WHERE SpecificTaskID = @SpecID AND StudentID = @StudID;", connection)


        With cmd.Parameters
            .AddWithValue("@Score", score)
            .AddWithValue("@Perc", percentage)
            .AddWithValue("@Grade", grade)
            .AddWithValue("@SpecID", specificIDorder(cbxCurrentTasks.SelectedIndex))
            .AddWithValue("@StudID", id)
        End With

        connection.Open()
        cmd.ExecuteReader()
        connection.Close()

1 Ответ

1 голос
/ 31 мая 2019

Храните ваши объекты данных локально, чтобы вы могли быть уверены, что они закрыты и удалены. Блоки Using ... End Using делают это для вас, даже если есть ошибка.

Не используйте .AddWithValue. См. http://www.dbdelta.com/addwithvalue-is-evil/ и https://blogs.msmvps.com/jcoehoorn/blog/2014/05/12/can-we-stop-using-addwithvalue-already/#comment-8442, чтобы узнать причину. Вам нужно будет проверить базу данных для типов данных полей. Я только что догадался.

В Access имена параметров не имеют значения. Порядок их появления в операторе sql должен соответствовать порядку их добавления в коллекцию Parameters.

.ExecuteReader используется для извлечения записей. Вы хотите выполнить оператор Update, поэтому используйте .ExecuteNonQuery.

Я не уверен, что вы делаете с specificIDorder(cbxCurrentTasks.SelectedIndex Является ли specificIDorder функцией, которая возвращает некоторое значение на основе индекса, выбранного в поле со списком? Если нет, вам нужно переосмыслить значение этого параметра.

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    Using cn As New OleDbConnection("Your connection string")
        Using cmd As New OleDbCommand("Update tblStudentScores 
                                Set Score = @Score, 
                                Percentage = @Perc,
                                Grade = @Grade, 
                                CompletedTask = True 
                                WHERE 
                                SpecificTaskID = @SpecID 
                                And 
                                StudentID = @StudID;", cn)
            With cmd.Parameters
                .Add("@Score", OleDbType.Integer).Value = score
                .Add("@Perc", OleDbType.Integer).Value = percentage
                .Add("@Grade", OleDbType.VarChar).Value = grade
                .Add("@SpecID", OleDbType.Integer).Value = CInt(specificIDorder(cbxCurrentTasks.SelectedIndex))
                .Add("@StudID", OleDbType.Integer).Value = id
            End With
            cn.Open()
            cmd.ExecuteNonQuery()
        End Using
    End Using
End Sub
...