数据库在处理完所有命令后仍然锁定

时间:2016-08-04 12:06:59

标签: vb.net sqlite executenonquery

即使我已经处理完所有命令,数据库也会被锁定。我试图写入数据库,但是底部的INSERT命令失败了。我之前有过工作但由于某种原因它现在已经开始失败了。

Sub Btn_SubmitClick(sender As Object, e As EventArgs)

    If MsgBox("Are you sure?",vbYesNo,"Submit?") = 7 Then
        'returns to previous screen
    Else
        'commences insert into database

        Rows = (dataGridView1.RowCount - 1)

        While count < rows 

            'putting grid stuff into variables
            DateStart = dataGridView1.Rows(Count).Cells(0).Value.ToString
            DateEnd = dataGridView1.Rows(Count).Cells(2).Value.ToString 'note other way round
            TimeStart = dataGridView1.Rows(Count).Cells(1).Value.ToString
            TimeEnd = dataGridView1.Rows(Count).Cells(3).Value.ToString
            TotalHours = dataGridView1.Rows(Count).Cells(4).Value.ToString
            OccuranceNo = dataGridView1.Rows(Count).Cells(5).Value.ToString

            'fetching reason ID for Storage

            SQLcommand = SQLconnect.CreateCommand

            SQLcommand.CommandText = "SELECT Reason_ID FROM Reasons WHERE Reason_Name = '" & dataGridView1.Rows(Count).Cells(6).Value.ToString & "'"

            SQLreader = SQLcommand.ExecuteReader

            ReasonID = SQLreader("Reason_ID")

            SQLcommand.Dispose

            'fetching site ID for storage
            SQLcommand = SQLconnect.CreateCommand

            SQLcommand.CommandText = "SELECT Site_ID FROM Sites WHERE Site_Name = '" & dataGridView1.Rows(Count).Cells(7).Value.ToString & "'"

            SQLreader = SQLcommand.ExecuteReader

            SiteID = SQLreader("Site_ID")

            SQLcommand.Dispose

            Oncall = dataGridView1.Rows(Count).Cells(8).Value.ToString

            'increment counter
            Count = Count + 1

            'send to database

            SQLcommand = SQLconnect.CreateCommand

            SQLcommand.CommandText = "INSERT INTO Shifts (Staff_ID, Date_Shift_Start, Date_Shift_End, Time_Shift_Start, Time_Shift_End, Total_Hours, Occurance_No, Site_ID, On_Call_Req, Rate, Approved, Reason_ID) VALUES ('" & userID & "' , '" & DateStart &"' , '" & DateEnd & "' , '" & TimeStart & "' , '" & TimeEnd & "' , '" & TotalHours & "' , '" & OccuranceNo & "' , '" & SiteID & "' , '" & Oncall & "' , '"& "1" & "' , '" & "N" & "' , '" & ReasonID & "')"          
            SQLcommand.ExecuteNonQuery()

            SQLcommand.Dispose

        End While



        MsgBox("Ok")
    End If
End Sub

1 个答案:

答案 0 :(得分:2)

在显示的代码中有几件事情应该改变。由于在代码中没有声明ConnectionCommandReader对象,因此它们必须是您正在重用的全局对象。 不要这样做。

可能有一个持久连接的原因,但查询本质上非常具体,因此尝试重用DbCommandDataReader可能会适得其反。由于这些与DbConnection密切配合,因此可能发生各种各样的坏事。这意味着问题的根源可能是代码中的 where

以下内容将循环通过DGV以插入多行。

Dim SQL = "INSERT INTO Sample (Fish, Bird, Color, Value, Price) VALUES (@f, @b, @c, @v, @p)"

Using dbcon As New SQLiteConnection(LiteConnStr)
    Using cmd As New SQLiteCommand(SQL, dbcon)

        dbcon.Open()
        cmd.Parameters.Add("@f", DbType.String)
        cmd.Parameters.Add("@b", DbType.String)
        cmd.Parameters.Add("@c", DbType.String)
        cmd.Parameters.Add("@v", DbType.Int32)
        cmd.Parameters.Add("@p", DbType.Double)

        Dim fishName As String
        For Each dgvR As DataGridViewRow In dgv2.Rows

            ' skip the NewRow, it has no data
            If dgvR.IsNewRow Then Continue For

            ' look up from another table
            ' just to shorten the code
            userText = dgvR.Cells(0).Value.ToString()
            fishName = dtFish.AsEnumerable().
                              FirstOrDefault(Function(f) f.Field(Of String)("Code") = userText).
                              Field(Of String)("Fish")
            ' or
            'Dim drs = dtFish.Select(String.Format("Code = '{0}'", userText))
            'fishName = drs(0)("Fish").ToString()

            cmd.Parameters("@f").Value = fishName
            cmd.Parameters("@b").Value = dgvR.Cells(1).Value
            cmd.Parameters("@c").Value = dgvR.Cells(2).Value
            cmd.Parameters("@v").Value = dgvR.Cells(3).Value
            cmd.Parameters("@p").Value = dgvR.Cells(4).Value

            cmd.ExecuteNonQuery()
        Next
    End Using
End Using
  • 注意:与原始代码一样,没有数据验证 - 也就是说,它假定他们输入的内容始终有效。这很少是一个很好的假设。
  • 代码实现Using,它将声明并创建目标对象(dbCommands,connections)并在完成它们时将其处理掉。它们不能干扰其他地方的代码,因为它们只存在于该块中。
  • SQL参数用于简化代码并指定数据类型。连接SQL的副作用是,所有内容都以字符串形式传递!对于无类型的SQLite,这可能非常糟糕。
  • 我会避免在循环中触发多个查找查询。原始代码应该抛出InvalidOperationException,因为Read永远不会DataReader
    • 也许最好的方法是让SitesReasons成为DGV中的ComboBox列,用户可以看到任何文字,ValueMember会已经可用于存储的代码。
    • 答案中显示的另一个替代方案是使用数据预加载DataTable,然后使用一些扩展方法来查找所需的值。
    • 如果你&#34;必须&#34;使用读者,在他们自己的Using块中实现它们。
  • 使用For Each循环,它提供正在检查的实际行。
  • 我认真重新考虑将startDateTime这样的内容存储为个别DateTime字段的想法。

如果使用DB Provider对象,这些是基础知识。不能确定重构所显示的程序会解决任何问题,因为问题很可能是代码中的任何地方,因为DBProvider对象保持打开而不是处理掉。

要检查的另一件事是您可能正在使用的任何UI管理器。在您单击“保存”或“写入”按钮之前,其中许多会累积更改。在此期间,有些人将数据库锁定。

最后,即使此处的代码更短更简单,使用DataAdapterDataTable也可以让DGV中的新数据自动更新数据库:< / p>

rowsAffected = myDA.Update(myDT)

学习如何配置它可能需要30分钟。