无法将pdf文件保存到access数据库

Unable to save pdf file into access database

我正在尝试更新访问数据库中的现有记录 table 并保存一个 pdf 文件。 但是,我收到“没有为一个或多个参数指定值”错误。

请看下面的代码。任何帮助将不胜感激。

谢谢

Dim strsql As String
Dim settings As String = ConfigurationManager.ConnectionStrings("ABCBO.My.MySettings.db_abcdealsConnectionString").ConnectionString
Dim con As New OleDbConnection
Private Sub printtopdf_Click(sender As Object, e As EventArgs) Handles printtopdf.Click
    con.ConnectionString = settings
    Try
        Dim fs As New FileStream("E:\NewApp\test1.pdf", FileMode.Open, FileAccess.Read)
        strsql = "UPDATE ABC_DEALS SET CONFIRMATION_COPY = @AT1 WHERE DEAL_TICKET = '" & TextBox5.Text & "'"
        Dim cmd As New OleDbCommand(strsql, con)
        Dim byteArr(CInt(fs.Length)) As Byte
        fs.Read(byteArr, 0, fs.Length)
        fs.Close()
        con.Open()
        cmd.Parameters.Add("@AT1", OleDbType.Binary).Value = byteArr
        cmd.ExecuteNonQuery()
        con.Close()
    Catch exc As Exception
        MsgBox(exc.Message)
        con.Close()
    End Try
End Sub

FileStreamOleDbConnectionOleDbCommand 都有一个需要调用的 Dispose 方法,以便释放非托管资源。 Vb.net 提供 Using...End Using 块来为我们处理这个问题并关闭连接和流。数据访问代码中的 Using 块包括连接和命令。注意连接线后的逗号。

您试图在点击方法中做太多事情。将数据访问代码与其余部分分开。

总是使用参数。 TextBox5.Text 等用户输入可能会将恶意代码引入您的数据库。参数值不被数据库视为可执行代码。

将连接字符串传递给连接的构造函数。

CommandTextConnection 传递给命令的构造函数。

Execute...

之前不要打开连接

即使这不能解决问题,它也会让您更清楚地了解问题出在哪里。放置一个断点并逐步执行代码检查变量值。

Private settings As String = ConfigurationManager.ConnectionStrings("ABCBO.My.MySettings.db_abcdealsConnectionString").ConnectionString

Private Sub printtopdf_Click(sender As Object, e As EventArgs) Handles Button1.Click 'printtopdf.Click
    Dim byteArr As Byte()
    Dim path As String = "E:\NewApp\test1.pdf"
    Try
        Using fs As New FileStream(path, FileMode.Open, FileAccess.Read)
            ReDim byteArr(CInt(fs.Length))
            fs.Read(byteArr, 0, CInt(fs.Length))
        End Using
        Dim Updated = UpdateDatabase(byteArr, CInt(TextBox5.Text))
        MessageBox.Show($"{Updated} has been successfully updated.")
    Catch exc As Exception
        MsgBox(exc.Message)
    End Try
End Sub

Private Function UpdateDatabase(PDF As Byte(), Ticket As Integer) As Integer
    Dim strsql = "UPDATE ABC_DEALS SET CONFIRMATION_COPY = @AT1 WHERE DEAL_TICKET = @Ticket;"
    Dim RecordsUpdated As Integer
    Using con As New OleDbConnection(settings),
         cmd As New OleDbCommand(strsql, con)
        cmd.Parameters.Add("@AT1", OleDbType.Binary).Value = PDF
        cmd.Parameters.Add("@Ticket", OleDbType.Integer).Value = Ticket
        con.Open()
        RecordsUpdated = cmd.ExecuteNonQuery()
    End Using
    Return RecordsUpdated
End Function

编辑

Private Function GetByteArrayFromFile(FilePath As String) As Byte()
    Dim file As Byte()
    Using stream As New FileStream(FilePath, FileMode.Open, FileAccess.Read),
            reader As New BinaryReader(stream)
        file = reader.ReadBytes(CInt(stream.Length))
    End Using
    Return file
End Function

Private Sub printtopdf_Click(sender As Object, e As EventArgs) Handles Button1.Click 'printtopdf.Click
    Dim path As String = "E:\NewApp\test1.pdf"
    Dim byteArr = GetByteArrayFromFile(path)
    Try
        Dim Updated = UpdateDatabase(byteArr, CInt(TextBox5.Text))
        MessageBox.Show($"{Updated} has been successfully updated.")
    Catch exc As Exception
        MsgBox(exc.Message)
    End Try
End Sub

编辑 2

我看到 3 个地方需要更改代码以适应 Long。我在代码中添加了验证 TryParse 以确保输入的类型正确。

旧代码 1

Dim Updated = UpdateDatabase(byteArr, CInt(TextBox5.Text))

新代码 1

    Dim ticket As Long
    If Not Long.TryParse(TextBox5.Text, ticket) Then
        MessageBox.Show("Please enter a valid ticket number")
        Exit Sub
    End If
    Dim Updated = UpdateDatabase(byteArr, ticket)

旧代码 2

Private Function UpdateDatabase(PDF As Byte(), Ticket As Integer) As Integer

新代码 2 注意:return 类型保持整数。

Private Function UpdateDatabase(PDF As Byte(), Ticket As Long) As Integer

旧代码 3

cmd.Parameters.Add("@Ticket", OleDbType.Integer).Value = Ticket

新代码 3 OleDbType.BigInt 似乎映射到 Int64。在 Access 中,该字段应为 Number 8 字节。对此并不乐观。你可能需要玩一下它。

    cmd.Parameters.Add("@Ticket", OleDbType.BigInt).Value = Ticket

最后回顾

Private Sub printtopdf_Click(sender As Object, e As EventArgs) Handles Button1.Click 'printtopdf.Click
    Dim path As String = "E:\NewApp\test1.pdf"
    Dim byteArr = GetByteArrayFromFile(path)
    Try
        If String.IsNullOrEmpty(TextBox5.Text) Then
            MessageBox.Show("Please enter a valid ticket number")
            Exit Sub
        End If
        Dim Updated = UpdateDatabase(byteArr, TextBox5.Text)
        MessageBox.Show($"{Updated} has been successfully updated.")
    Catch exc As Exception
        MsgBox(exc.Message)
    End Try
End Sub

Private settings As String = ConfigurationManager.ConnectionStrings("ABCBO.My.MySettings.db_abcdealsConnectionString").ConnectionString

Private Function UpdateDatabase(PDF As Byte(), Ticket As String) As Integer
    Dim strsql = "UPDATE ABC_DEALS SET CONFIRMATION_COPY = @AT1 WHERE DEAL_TICKET = @Ticket;"
    Dim RecordsUpdated As Integer
    Using con As New OleDbConnection(settings),
            cmd As New OleDbCommand(strsql, con)
        cmd.Parameters.Add("@AT1", OleDbType.LongVarBinary).Value = PDF
        cmd.Parameters.Add("@Ticket", OleDbType.VarChar).Value = Ticket
        con.Open()
        RecordsUpdated = cmd.ExecuteNonQuery()
    End Using
    Return RecordsUpdated
End Function

Private Function GetByteArrayFromFile(FilePath As String) As Byte()
    Dim file As Byte()
    Using stream As New FileStream(FilePath, FileMode.Open, FileAccess.Read),
        reader As New BinaryReader(stream)
        file = reader.ReadBytes(CInt(stream.Length))
    End Using
    Return file
End Function