在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()
阶段立即失败并出现数据库锁定错误,但我无法理解原因。我没有正确处理我的数据库关闭吗?我的印象是SQLite只在写入时创建锁定,这在所描述的显式情况下永远不会发生。
如果我没有“添加”项目到打印队列(程序的基本功能),程序将正常关闭。
答案 0 :(得分:2)
执行后处理每个命令应该解决问题
dbLocalQuery.ExecuteNonQuery()
dbLocalQuery.Dispose()
问题是因为你有删除和插入命令同时执行导致错误
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()
答案 1 :(得分:0)
我通过用本地系统注册表存储替换数据库来解决这个问题。这有利于使用户不可知。数据库设置用作默认值'对于新用户。
的onload:
'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