Vb.net SQLite闭锁原因的诊断
在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
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()
参考:
我会给你最好的答案,因为它解决了问题,而不是扔进垃圾箱。:)