Vb.net SQLite闭锁原因的诊断

Vb.net SQLite闭锁原因的诊断,vb.net,sqlite,Vb.net,Sqlite,在vb.net应用程序中,我遇到了这样一种情况,即用户在表单的一部分中的操作正在创建一个SQLite锁,该锁会导致应用程序中出现问题(在本例中,关闭它) 以下是当用户向要打印的项目列表添加数据时调用的子程序: Private Sub btnAdd_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnAdd.Click ' Add item to printQueue => rege

在vb.net应用程序中,我遇到了这样一种情况,即用户在表单的一部分中的操作正在创建一个SQLite锁,该锁会导致应用程序中出现问题(在本例中,关闭它)

以下是当用户向要打印的项目列表添加数据时调用的子程序:

Private Sub btnAdd_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnAdd.Click
    ' Add item to printQueue => regenerate listPrint.items
    Dim queueItem As New Dictionary(Of String, String)
    queueItem("quantity") = inputQuantity.Value.ToString
    queueItem("description") = textDesc.Text
    queueItem("sizeUK") = inputSize.Value.ToString.Replace(".5", "½").Replace(".0", "")
    queueItem("sku") = listStyles.SelectedItem.ToString
    queueItem("colour") = textColour.Text
    queueItem("date") = textDateCode.Text
    queueItem("name") = textName.Text

    Try
        queueItem("sizeEU") = sizeEU(inputSize.Value).ToString.Replace(".5", "½")
    Catch ex As Exception
        queueItem("sizeEU") = "??"
    End Try

    ' US Size: M = UK + 1; F = UK + 1.5
    queueItem("sizeUS") = (inputSize.Value + 1.5 - (chkSex.CheckState * 0.5)).ToString.Replace(".5", "½")

    ' Add the image data as a string
    dbLocalQuery = New SQLiteCommand("SELECT * FROM tblImages WHERE id ='" & listStyles.SelectedItem.ToString & "'", dbLocal)

    If dbLocal.State = ConnectionState.Closed Then
        dbLocal.Open()
    End If

    Dim r As SQLiteDataReader = dbLocalQuery.ExecuteReader()

    Try
        r.Read()
        queueItem("image") = byte2string((r("image")))
    Catch ex As Exception
        queueItem("image") = settings("imgNotFound")
    Finally
        If dbLocal.State = ConnectionState.Open Then
            dbLocal.Close()
        End If
    End Try

    printQueue.Add(printQueue.Count + 1, queueItem)
    MsgFrame.Items.Add(printQueue(printQueue.Count)("sku") & " x" & printQueue(printQueue.Count)("quantity"))
    MsgFrame.SelectedIndex = MsgFrame.Items.Count - 1
    ' Update print queue list
    populateList()
End Sub
数据库中被查询触及的唯一表是tblImages。即使如此,连接完成后也会关闭

关闭表单时,将调用一个函数,该函数捕获写入字典(称为加载时设置)的数据,并将其重新插入数据库

Public Function dbLocalSave() As Boolean
    'Recreates the tblSettings from current values stored in settings 
    Try
        If dbLocal.State = ConnectionState.Closed Then
            dbLocal.Open()
        End If

        If dbLocal.State = ConnectionState.Open Then
            MsgFrame.Items.Add("Flushing local settings table")
            MsgFrame.SelectedIndex = MsgFrame.Items.Count - 1

            For Each pair In settings
                Debug.Print("+ tblSettings: " & pair.Key & " = " & pair.Value)

                dbLocalQuery = New SQLiteCommand("DELETE FROM tblSettings where name = '" & pair.Key & "';", dbLocal)
                dbLocalQuery.ExecuteNonQuery()

                dbLocalQuery = New SQLiteCommand("INSERT INTO tblSettings (`name`,`value`) VALUES ('" & pair.Key & "','" & pair.Value & "');", dbLocal)
                dbLocalQuery.ExecuteNonQuery()
            Next
            Return True
        Else
            Return False
        End If
    Catch sqlex As SQLiteException
        MessageBox.Show(sqlex.Message, "SQL Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
    Catch ex As Exception
        MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
    Finally
        If dbLocal.State = ConnectionState.Open Then
            dbLocal.Close()
        End If
    End Try

End Function
此函数在
dbLocalQuery.ExecuteNonQuery()
阶段立即失败,并出现db锁错误,但我无法理解原因。我是否没有正确处理数据库关闭?我的印象是SQLite只在写操作上创建锁,这在所描述的显式情况中从未发生过


如果我没有将项目“添加”到打印队列(程序的基本功能),程序将正常关闭。

我通过使用本地系统注册表存储替换数据库写入来解决这个问题。这样做的好处是用户不可知。db设置用作新用户的“默认设置”

加载:

'Get settings from Registy - if key not present, get defaults from db.

    Dim regkey As RegistryKey = Registry.CurrentUser.OpenSubKey("Software\Foot Shop Ltd\" & Application.ProductName, True)

    If regkey Is Nothing Then
        'Key doesn't exist, populate settings from DB

        Try
            Debug.Print("Opening Database...")
            If dbLocal.State = ConnectionState.Closed Then
                dbLocal.Open()
            End If

            Debug.Print("Database Open - " & Application.StartupPath & "\boxLabels.db")

            dbLocalQuery = New SQLiteCommand("SELECT * FROM tblSettings", dbLocal)

            'Get default settings from SQLite DB, write to registry
            Dim r As SQLiteDataReader = dbLocalQuery.ExecuteReader()
            While r.Read()
                settings.Add(CStr(r("name")), CStr(r("value")))
                Debug.Print("Default Used: " & CStr(r("name")) & " = " & CStr(r("value")))
            End While
            r.Close()

        Catch sqlex As SQLiteException
            Debug.Print(sqlex.Message)
        Catch ex As Exception
            MessageBox.Show(ex.Message, "Loading Exception", MessageBoxButtons.OK, MessageBoxIcon.Error)
            Application.Exit()
            Exit Sub
        Finally
            If dbLocal.State = ConnectionState.Open Then
                dbLocal.Close()
            End If
        End Try

    Else
        'build settings from registry

        Dim names As String() = regkey.GetValueNames

        ' Open the next subkey if any and call myself.
        Dim value As String
        Dim data As String
        For Each value In names
            data = regkey.GetValue(value, Nothing)
            settings.Add(value.ToString, data.ToString)
            Debug.Print("Reg Value Used: " & value.ToString & " = " & data.ToString)
        Next

    End If

    regkey.Close()
dbLocalSave:

    Public Function dbLocalSave() As Boolean
    'Recreates the tblSettings from current values stored in settings 
    Try
         MsgFrame.Items.Add("Flushing local settings table")
        MsgFrame.SelectedIndex = MsgFrame.Items.Count - 1

        For Each pair In settings
            Debug.Print("+ tblSettings: " & pair.Key & " = " & pair.Value)
            My.Computer.Registry.SetValue("HKEY_CURRENT_USER\Software\Foot Shop Ltd\" & Application.ProductName, pair.Key, pair.Value)
        Next

    Catch ex As Exception
        MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
        Return False
    End Try

    Return True
End Function

执行后处理每个命令应该可以解决问题

dbLocalQuery.ExecuteNonQuery()
dbLocalQuery.Dispose()
问题是因为delete和insert命令同时执行,这导致了错误

            dbLocalQuery = New SQLiteCommand("DELETE FROM tblSettings where name  = '" & pair.Key & "';", dbLocal)
            dbLocalQuery.ExecuteNonQuery()
            'insert here '
            dbLocalQuery.dispose()
            dbLocalQuery = New SQLiteCommand("INSERT INTO tblSettings (`name`,`value`) VALUES ('" & pair.Key & "','" & pair.Value & "');", dbLocal)
            dbLocalQuery.ExecuteNonQuery()
            'here also '
            dbLocalQuery.dispose()
参考:

我会给你最好的答案,因为它解决了问题,而不是扔进垃圾箱。:)