Vb.net 我在这里做错了什么;ExecuteOnQuery需要打开且可用的连接。连接';的当前状态已关闭。';?我使用Access 2016

Vb.net 我在这里做错了什么;ExecuteOnQuery需要打开且可用的连接。连接';的当前状态已关闭。';?我使用Access 2016,vb.net,ms-access-2016,Vb.net,Ms Access 2016,当我试图通过我的应用程序添加“books”时,它总是说“System.InvalidOperationException:“ExecuteOnQuery需要一个打开且可用的连接。该连接的当前状态是关闭的。”但我已经建立了OLEDB连接。我在这里犯了什么错误 Public Class clsBookDA Private Shared dcnBooks As New _ OleDbConnection("Provider=Microsoft.Jet.OLEDB.12

当我试图通过我的应用程序添加“books”时,它总是说“System.InvalidOperationException:“ExecuteOnQuery需要一个打开且可用的连接。该连接的当前状态是关闭的。”但我已经建立了OLEDB连接。我在这里犯了什么错误

Public Class clsBookDA
    Private Shared dcnBooks As New _
        OleDbConnection("Provider=Microsoft.Jet.OLEDB.12.0;DataSource=C:\Temp\books.accdb")
    Private Shared books As New ArrayList()

    Private Shared aBook As clsBook
    Private Shared aBookdID, anAuthor, aTitle As String
    Private Shared aPurchasePrice, aSalePrice As Decimal
    Private Shared anInventory As Integer

    Public Shared Sub Initialize()
        dcnBooks.Open()
    End Sub
    Public Shared Sub Terminate()
        dcnBooks.Close()
        dcnBooks.Dispose()
    End Sub
    Public Shared Function GetAll() As ArrayList
        Dim dapBooks As New OleDbDataAdapter()
        Dim dtbBooks As New DataTable()
        Dim drwBook As DataRow

        dapBooks = New OleDbDataAdapter("Select*From Books", dcnBooks)
        dapBooks.Fill(dtbBooks)

        books.Clear()
        For Each drwBook In dtbBooks.Rows
            aBookdID = drwBook("BookID")
            anAuthor = drwBook("Author")
            aTitle = drwBook("Title")
            aPurchasePrice = drwBook("PurchasePrice")
            aSalePrice = drwBook("SalePrice")
            anInventory = drwBook("Inventory")
            Dim aBook As New clsBook(aBookdID, anAuthor, aTitle, aPurchasePrice, aSalePrice, anInventory)
            books.Add(aBook)
        Next
        Return books
    End Function
    Public Shared Sub Add(ByVal aBook As clsBook)
        Dim dapBooks As New OleDbDataAdapter()
        Dim sqlQuery As String = "INSERT INTO Books" & "VALUES('" &
            aBook.BookID & "','" & aBook.Author & "','" & aBook.Title & "','" &
            aBook.PurchasePrice & "','" & aBook.SalePrice & "','" &
            aBook.Inventory & "')"

        dapBooks.UpdateCommand = New OleDbCommand(sqlQuery, dcnBooks)
        dapBooks.UpdateCommand.ExecuteNonQuery()
    End Sub
    Public Shared Sub Update(ByVal aBook As clsBook)
        Dim dapBooks As New OleDbDataAdapter()
        Dim sqlQuery As String = "UPDATE Books" & "SET Author = '" &
            aBook.Author & "', Title = '" & aBook.Title & "', PurchasePrice ='" &
            aBook.PurchasePrice & "', SalePrice= '" & aBook.SalePrice &
            "', Inventory= '" & aBook.Inventory & "'" &
            "WHERE BookID = '" & aBook.BookID & "'"

        dapBooks.UpdateCommand = New OleDbCommand(sqlQuery, dcnBooks)
        dapBooks.UpdateCommand.ExecuteNonQuery()
    End Sub

    Public Shared Sub Delete(ByVal aBook As clsBook)
        Dim dapBooks As New OleDbDataAdapter()
        Dim sqlQuery As String = "DELETE FROM Books WHERE BookID='" &
            aBook.BookID & "'"

        dapBooks.UpdateCommand = New OleDbCommand(sqlQuery, dcnBooks)
        dapBooks.UpdateCommand.ExecuteNonQuery()
    End Sub
End Class

有关
ArrayList
的信息,请参见

像连接和命令这样的数据库对象需要尽快关闭和释放。最好将它们保留在使用它们的方法中。使用块可以确保即使出现错误,也会清理这些对象

始终使用参数以避免Sql注入。在Access中,参数在sql语句中的显示顺序必须与参数添加到参数集合的顺序相同

DataAdapter
s具有代码中未使用的额外功能。使用“较轻重量”命令对象

我看到您似乎在连接的sql字符串中的数字类型周围加了单引号。如果这些确实是Access中的数字,则会导致问题。参数通过提供数据库类型来避免此问题,因此sql字符串中的中不需要单引号

不要将整个
clsBook
传递给delete sub。只需传递id即可

我将让您重写更新代码

Public Class clsBookDA
    Private Shared ConStr As String = "Provider=Microsoft.Jet.OLEDB.12.0;DataSource=C:\Temp\books.accdb"

    Public Shared Function GetAll() As List(Of clsBook)
        Dim dtbBooks As New DataTable()
        Using cn As New OleDbConnection(ConStr),
                cmd As New OleDbCommand("Select * From Books", cn)
            cn.Open()
            Using reader = cmd.ExecuteReader
                dtbBooks.Load(reader)
            End Using
        End Using
        Dim lst As New List(Of clsBook)
        For Each drwBook As DataRow In dtbBooks.Rows
            Dim bk As New clsBook(drwBook("BookID").ToString, drwBook("Author").ToString, drwBook("Title").ToString, CDec(drwBook("PurchasePrice")), CDec(drwBook("SalePrice")), CInt(drwBook("Inventory")))
            lst.Add(bk)
        Next
        Return lst
    End Function
    Public Shared Sub Add(ByVal aBook As clsBook)
        Dim sqlQuery As String = "INSERT INTO Books VALUES(@ID, @Author, @Title, @PurchasePrice, @SalePrice, @Inventory);"
        Using cn As New OleDbConnection(ConStr),
                cmd As New OleDbCommand(sqlQuery, cn)
            With cmd.Parameters
                .Add("@ID", OleDbType.VarChar).Value = aBook.BookID
                .Add("@Author", OleDbType.VarChar).Value = aBook.Author
                .Add("@Title", OleDbType.VarChar).Value = aBook.Title
                .Add("@PurchasePrice", OleDbType.Decimal).Value = aBook.PurchasePrice
                .Add("@SalePrice", OleDbType.Decimal).Value = aBook.SalePrice
                .Add("@Inventory", OleDbType.Integer).Value = aBook.Inventory
            End With
            cn.Open()
            cmd.ExecuteNonQuery()
        End Using
    End Sub
    Public Shared Sub Update(ByVal aBook As clsBook)
        'To do
    End Sub

    Public Shared Sub Delete(BookID As String)
        Dim sqlQuery As String = "DELETE FROM Books WHERE BookID=@BookID;"
        Using cn As New OleDbConnection(ConStr),
                cmd As New OleDbCommand(sqlQuery, cn)
            cmd.Parameters.Add("@BookID", OleDbType.VarChar).Value = BookID
            cn.Open()
            cmd.ExecuteNonQuery()
        End Using
    End Sub
End Class

Public Class clsBook
    Public Property BookID As String
    Public Property Author As String
    Public Property Title As String
    Public Property PurchasePrice As Decimal
    Public Property SalePrice As Decimal
    Public Property Inventory As Integer

    Public Sub New(id As String, auth As String, titl As String, purch As Decimal, sale As Decimal, inv As Integer)
        BookID = id
        Author = auth
        Title = titl
        PurchasePrice = purch
        SalePrice = sale
        Inventory = inv
    End Sub

End Class

有关
ArrayList
的信息,请参见

像连接和命令这样的数据库对象需要尽快关闭和释放。最好将它们保留在使用它们的方法中。使用块可以确保即使出现错误,也会清理这些对象

始终使用参数以避免Sql注入。在Access中,参数在sql语句中的显示顺序必须与参数添加到参数集合的顺序相同

DataAdapter
s具有代码中未使用的额外功能。使用“较轻重量”命令对象

我看到您似乎在连接的sql字符串中的数字类型周围加了单引号。如果这些确实是Access中的数字,则会导致问题。参数通过提供数据库类型来避免此问题,因此sql字符串中的中不需要单引号

不要将整个
clsBook
传递给delete sub。只需传递id即可

我将让您重写更新代码

Public Class clsBookDA
    Private Shared ConStr As String = "Provider=Microsoft.Jet.OLEDB.12.0;DataSource=C:\Temp\books.accdb"

    Public Shared Function GetAll() As List(Of clsBook)
        Dim dtbBooks As New DataTable()
        Using cn As New OleDbConnection(ConStr),
                cmd As New OleDbCommand("Select * From Books", cn)
            cn.Open()
            Using reader = cmd.ExecuteReader
                dtbBooks.Load(reader)
            End Using
        End Using
        Dim lst As New List(Of clsBook)
        For Each drwBook As DataRow In dtbBooks.Rows
            Dim bk As New clsBook(drwBook("BookID").ToString, drwBook("Author").ToString, drwBook("Title").ToString, CDec(drwBook("PurchasePrice")), CDec(drwBook("SalePrice")), CInt(drwBook("Inventory")))
            lst.Add(bk)
        Next
        Return lst
    End Function
    Public Shared Sub Add(ByVal aBook As clsBook)
        Dim sqlQuery As String = "INSERT INTO Books VALUES(@ID, @Author, @Title, @PurchasePrice, @SalePrice, @Inventory);"
        Using cn As New OleDbConnection(ConStr),
                cmd As New OleDbCommand(sqlQuery, cn)
            With cmd.Parameters
                .Add("@ID", OleDbType.VarChar).Value = aBook.BookID
                .Add("@Author", OleDbType.VarChar).Value = aBook.Author
                .Add("@Title", OleDbType.VarChar).Value = aBook.Title
                .Add("@PurchasePrice", OleDbType.Decimal).Value = aBook.PurchasePrice
                .Add("@SalePrice", OleDbType.Decimal).Value = aBook.SalePrice
                .Add("@Inventory", OleDbType.Integer).Value = aBook.Inventory
            End With
            cn.Open()
            cmd.ExecuteNonQuery()
        End Using
    End Sub
    Public Shared Sub Update(ByVal aBook As clsBook)
        'To do
    End Sub

    Public Shared Sub Delete(BookID As String)
        Dim sqlQuery As String = "DELETE FROM Books WHERE BookID=@BookID;"
        Using cn As New OleDbConnection(ConStr),
                cmd As New OleDbCommand(sqlQuery, cn)
            cmd.Parameters.Add("@BookID", OleDbType.VarChar).Value = BookID
            cn.Open()
            cmd.ExecuteNonQuery()
        End Using
    End Sub
End Class

Public Class clsBook
    Public Property BookID As String
    Public Property Author As String
    Public Property Title As String
    Public Property PurchasePrice As Decimal
    Public Property SalePrice As Decimal
    Public Property Inventory As Integer

    Public Sub New(id As String, auth As String, titl As String, purch As Decimal, sale As Decimal, inv As Integer)
        BookID = id
        Author = auth
        Title = titl
        PurchasePrice = purch
        SalePrice = sale
        Inventory = inv
    End Sub

End Class

您究竟在哪里调用用于打开到db的连接的Initialize方法?另外,您是否会考虑使用Using子句来实现您的连接处理,以防止由于将连接保留为openArrayList而导致的问题???你的课本几岁了?ArrayList不应在新代码中使用。签出Lis(Of T)您在哪里调用初始化方法来打开与数据库的连接?另外,您是否会考虑使用Using子句来实现您的连接处理,以防止由于将连接保留为openArrayList而导致的问题???你的课本几岁了?ArrayList不应在新代码中使用。查看Lis(Of T)@BartHofland当命令被释放时,它会处理它的连接属性,并且也会处理它。@BartHofland感谢您提供的信息。我是从一个比我经验丰富得多的人那里得到这个结论的。我相信这个解释,但我并不完全理解。我将回到使用using显式包装连接的旧模式。@BartHofland我已经更正了我的代码。@BartHofland我想知道我编辑了什么,因为它不是这个答案。哦,好吧。现在是凌晨4点。该睡觉了。@BartHofland当命令被释放时,它会处理它的连接属性,并且也会处理它。@BartHofland感谢您提供的信息。我是从一个比我经验丰富得多的人那里得到这个结论的。我相信这个解释,但我并不完全理解。我将回到使用using显式包装连接的旧模式。@BartHofland我已经更正了我的代码。@BartHofland我想知道我编辑了什么,因为它不是这个答案。哦,好吧。现在是凌晨4点。该睡觉了。