Vb.NET проблема синтаксиса обновления SQL MS Access

Я долбил об этом в течение нескольких часов, но не получил его правильно, поэтому я решил опубликовать.

Мой Vb.NET приложение имеет 2 jpg на жестком диске. Одно естьLowRes, а другое есть HighRes. Я хочу сохранить оба изображения в одной записи в базе данных Microsoft Access 2007 через INSERT, который работает нормально, а затем UPDATEдобавить второй. То UPDATEне работает.

Я собрал кучу кода, который я нашел в интернете для INSERTкода (учась, как я иду), и в конце концов понял, что на самом деле работает. Тем не менее, попытка настроить функцию, чтобы сделать обновление, чтобы добавить второе изображение оказывается трудным. Я подозреваю, что его что-то делать со мной, указывая параметры неправильно?

База данных имеет 1 таблицу Recordsс 3 столбцами RecordID(которая является текстом и первичным ключом autonumber, который извлекается изForm1.Tb_RecordID.Text), HighRes(который является OLE) и LowRes(который также является OLE). База данных имеет имя Database.accdb.

Я вызываю подпрограмму с:

Save_To_Database("LowProfile.jpg", "LowRes")

если я хочу, чтобы INSERTизображение OLE в столбце «LowRes». Я тогда позвоню

Update_To_Database("HighProfile.jpg", "HighRes")

чтобы обновить запись с HighResизображением. В конечном итоге я хочу объединить эти функции один к одному и использовать ByVals, чтобы определить, следует ли его обновлять или вставлять.

Это работает отлично:

Sub Save_To_Database(ByVal Filename As String, ByVal Res As String)

    Dim cnString As String = "PROVIDER=Microsoft.ACE.OLEDB.12.0;Data Source=Database.accdb"
    Dim theQuery As String = "INSERT INTO Records([RecordID],[" & Res & "]) values (" & Form1.Tb_RecordID.Text & ", @Img)"

    Try
        Dim fs As FileStream
        fs = New FileStream(Filename, FileMode.Open, FileAccess.Read)
        Dim picByte As Byte() = New Byte(fs.Length - 1) {}
        fs.Read(picByte, 0, System.Convert.ToInt32(fs.Length))
        fs.Close()
        Dim CN As New OleDbConnection(cnString)
        CN.Open()
        Dim imgParam As New OleDbParameter()
        imgParam.OleDbType = OleDbType.Binary
        imgParam.ParameterName = "Img"
        imgParam.Value = picByte
        Dim cmd As New OleDbCommand(theQuery, CN)
        cmd.Parameters.Add(imgParam)
        cmd.ExecuteNonQuery()
        MessageBox.Show("Image successfully saved.")
        cmd.Dispose()
        CN.Close()
        CN.Dispose()
    Catch ex As Exception
        MessageBox.Show(ex.Message)
    End Try

End Sub

Однако мой UPDATEкод завершается ошибкой синтаксиса инструкции SQL:

Sub Update_To_Database(ByVal Filename As String, ByVal Res As String)

    Dim cnString As String = "PROVIDER=Microsoft.ACE.OLEDB.12.0;Data Source=Database.accdb"
    Dim theQuery As String = "UPDATE Records SET ([" & Res & "]) values (@Img) WHERE RecordID =" & Form1.Tb_RecordID.Text

    MsgBox(theQuery)

    Try
        Dim fs As FileStream
        fs = New FileStream(Filename, FileMode.Open, FileAccess.Read)
        Dim picByte As Byte() = New Byte(fs.Length - 1) {}
        fs.Read(picByte, 0, System.Convert.ToInt32(fs.Length))
        fs.Close()
        Dim CN As New OleDbConnection(cnString)
        CN.Open()
        Dim imgParam As New OleDbParameter()
        imgParam.OleDbType = OleDbType.Binary
        imgParam.ParameterName = "Img"
        imgParam.Value = picByte
        Dim cmd As New OleDbCommand(theQuery, CN)
        cmd.Parameters.Add(imgParam)
        cmd.ExecuteNonQuery()
        MessageBox.Show("Image successfully saved.")
        cmd.Dispose()
        CN.Close()
        CN.Dispose()
    Catch ex As Exception
        MessageBox.Show(ex.Message)
    End Try

End Sub

Кто — нибудь видит проблему? Или как улучшить код?

1 ответ

  1. Первоначальная проблема заключается в том, что вы пытались написать инструкцию update, используя синтаксис инструкции insert. Простым решением было бы просто изменить инструкцию update на правильный синтаксис.

    Однако в вашем коде есть ряд вещей, которые можно и нужно изменить, поэтому я написал пример, основанный на вашем коде, который все еще может быть улучшен дальше:

    Sub Save_To_Database(ByVal Filename As String, ByVal RecordId As String, ByVal IsHighResolution As Boolean, ByVal IsNew As Boolean)
    
        Dim theQuery As String
        Dim cnString As String = "PROVIDER=Microsoft.ACE.OLEDB.12.0;Data Source=Database.accdb"
    
        If IsNew Then
            theQuery = "INSERT INTO Records([RecordID],[" & IIf(IsHighResolution, "HighRes", "LowRes") & "]) values (@RecordId, @Img)"
        Else
            theQuery = "UPDATE Records SET " & IIf(IsHighResolution, "HighRes", "LowRes") & " = @Img WHERE RecordID = @RecordId"
        End If
    
        Try
            Using fs As New FileStream(Filename, FileMode.Open, FileAccess.Read)
                Dim picByte As Byte() = New Byte(fs.Length - 1) {}
                fs.Read(picByte, 0, System.Convert.ToInt32(fs.Length))
                Using CN As New OleDbConnection(ConnectionString)
    
                    Dim cmd As New OleDbCommand(theQuery, CN)
                    cmd.Parameters.Add("Img", OleDbType.Binary).Value = picByte
                    cmd.Parameters.Add("@RecordId", OleDbType.Integer).Value = RecordId
    
                    CN.Open()
                    cmd.ExecuteNonQuery()
                    MessageBox.Show("Image successfully saved.")
                End Using
            End Using
    
        Catch ex As Exception
            MessageBox.Show(ex.Message)
        End Try
    
    End Sub
    

    Достопримечательность:

    1. Insert и update теперь обрабатываются тем же методом, только разница является логическим параметром, который указывает, является ли это новая запись или существующая.

    2. Запросы теперь защищены от внедрения sql. Единственное сцепление здесь-это имя столбца, которое нельзя параметризовать в sql, но оно решается внутри самой суб. При использовании sub вы передаете только логическое значение, указывающее, что это изображение с высоким разрешением.

    3. Блок Using рекомендуется использовать всякий раз, когда вы используете что-либо, что реализует интерфейс IDisposable. Это гарантирует правильное сближение и удаление даже в случае исключения.

    4. Параметры кода упрощены.