显示DataGrid后,SQLite数据库被锁定

时间:2016-08-09 16:43:26

标签: .net vb.net sqlite

我有一个Sub来显示DataGridView上的数据,但是在这个sub之后我无法添加文件,因为我得到了一个数据库被锁定的消息。

我尝试过使用 SQLiteConnection.ClearAllPools()

和 所以GC.Collect()

但是是一样的。我还试着让Using块尽可能小。

在此代码之后锁定数据库的原因是什么?

Private Sub LoadDataGridView1()

    Dim connLoadDataGrid = New SQLiteConnection("Data Source=myDataBase.sqlite;Version=3")

    Try
        Using (connLoadDataGrid)

            connLoadDataGrid.Open()

            Dim sql = "SELECT * FROM users"

            Dim cmdDataGrid As SQLiteCommand = New SQLiteCommand(sql, connLoadDataGrid)

            'Load data on a Table
            Dim da As New SQLiteDataAdapter
            da.SelectCommand = cmdDataGrid
            Dim dt As New DataTable
            da.Fill(dt)
            DataGridView1.DataSource = dt

            'Change the name of the columns
            With DataGridView1
                .RowHeadersVisible = False
                .Columns(0).HeaderCell.Value = "ID"
                .Columns(1).HeaderCell.Value = "Name"
                .Columns(2).HeaderCell.Value = "Type"
                .Columns(3).HeaderCell.Value = "Notes"
            End With

            'Autoadjust the columns
            DataGridView1.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.AllCellsExceptHeader)

            Dim readerDataGrid As SQLiteDataReader = cmdDataGrid.ExecuteReader()

       End Using

    Catch ex As Exception
        MsgBox(ex.ToString())
    End Try

End Sub

1 个答案:

答案 0 :(得分:1)

从根本上说,你的代码会留下一些其他不受干扰的东西:DbCommandDataAdapter,最重要的是,在末尾创建一个奇怪的DataReader,它仍然是开放的和活着的。任何实现Dispose方法的东西都应该在Using块中创建并使用,以确保它被释放并释放资源。

这对于SQLite尤其重要,因为数据库只是一个文件。

对于基本的添加/更改/删除应用,您可以创建一个DataAdapter,它将在您的应用/表单的生命周期中存在,并且能够为您执行所有数据库操作

' form/class level objects
Private daLite As SQLiteDataAdapter
Private dtLite As DataTable

初始化数据库提供程序对象:

' spell out your SQL
Dim SQL = "SELECT Id, Name, Fish, Bird, Color, Price FROM Sample"

' persistent datatadapter
daLite = New SQLiteDataAdapter(SQL, LiteConnStr)
dtLite = New DataTable

' teach the DA how to do everything
Dim cb As New SQLiteCommandBuilder(daLite)
daLite.InsertCommand = cb.GetInsertCommand
daLite.UpdateCommand = cb.GetUpdateCommand
daLite.DeleteCommand = cb.GetDeleteCommand

' load schema, table
daLite.FillSchema(dtLite, SchemaType.Source)
daLite.Fill(dtLite)

dgv1.DataSource = dtLite

传递连接字符串而不是连接对象,让DataAdapter创建自己的连接,它将根据需要打开和关闭。最后,它知道如何从数据库中添加,插入和删除,因为它“保留”了那些命令对象。您可能不需要在应用程序中使用任何其他SQL。

请注意,DataTable中的每一行都有一个RowState,表示是否添加,删除或更改了这一行,因此您可以在更新数据库之前累积多项更改:

' dataadapter will open its connection, then close 
Dim rows = daLite.Update(dtLite)

添加所有新行,更新已更新的行,删除已删除的行。 rows将是它们的总数。

另一个好处是您可以“刷新”行。如果在应用程序外部进行了更改(例如,您在UI数据库浏览器中)。稍后再次执行daLite.Fill(dtLite),只会选择这些更改。

备注

  • 在这种情况下,您将在过程中(或任何地方)处置DBCommand,DBConnection等,因为计划是反复使用它。
  • 您应该拼出您的SQL来控制DGV列显示的顺序。
    • 要使上述工作正常,主键需要成为SQL的一部分。
  • 顺便提一下,更改DGV HeaderText不会更改列名,只会更改显示的文本。
  • 使用此类内容进行批量导入时,Transaction会加快速度。

这仅适用于简单的一个表查询,因为您的查询似乎是。