避免并发 - 首先是 DGV 错误
本文关键字:DGV 错误 并发 | 更新日期: 2023-09-27 18:33:46
我感觉我没有按照我应该的方式使用表格适配器。 我在这里阅读了几个问题和这篇关于处理数据网格视图(DGV(中的并发错误的MS文章。
在我的设置中,我一次只有一个用户访问该表,并且它将位于该人工作的本地HD上。 我在选项卡控件中的多个选项卡上使用多个 DGV。 DGV 绑定到访问数据库中的表。 当用户尝试在两行或多行的多个单元格上输入值时,他们将在第二行的第二个单元格之后遇到并发错误。 处理并发错误一次并重新填充 DGV 以更新主键列后,它们不会有任何错误。
返回到 DGV 中的现有值也不会导致错误,似乎只有在键列(用户不输入但可以按其排序(Is DBNull
时才会发生。
这是我到目前为止得到的:
Dim m_DtChemical As New DataTable
Dim ChemicalAdapter As OleDbDataAdapter
Dim m_Bsource As New BindingSource
Sub FillChemicalDataGrid()
ChemicalAdapter = New OleDbDataAdapter("Select * From Chemicals", ConMain)
m_DtChemical.Clear()
ChemicalAdapter.Fill(m_DtChemical)
m_Bsource.DataSource = m_DtChemical
ChemicalDataGridView.DataSource = m_Bsource
End Sub
Sub UpdateChemicalsDatabase()
Try
Dim ObjComander As New OleDbCommandBuilder(ChemicalAdapter)
ChemicalAdapter.Update(m_DtChemical)
Catch ex2 As DBConcurrencyException
OhGodImStuckErrorHandler()
MsgBox("Concurrency Error. Reloading Table.")
FillChemicalDataGrid()
Catch ex As Exception
MsgBox("There was an error updating to the database. " & ex.Message)
WriteToErrorLog(ex.Message, ex.StackTrace, ex.GetHashCode, ex.Source, ex.ToString)
End Try
End Sub
Private Sub ChemicalDataGridView_RowValidated(ByVal sender As Object, ByVal e As _
System.Windows.Forms.DataGridViewCellEventArgs) Handles ChemicalDataGridView.RowValidated 'tried CellLeave, CellEnter, CellValidated...etc
Call UpdateChemicalsDatabase()
End Sub
我试图导致合并和更新发生,尤其是If IsDBNull(DGV(0, Xrow).Value) = true
我在我想做的事情上是否偏离了一步? 它似乎仅来自 ID(主键列(实际上是 DBNull 的实例。 有没有更好的方法来处理这个问题? 与其处理并发错误,我觉得如果我能弄清楚如何操作,我应该能够首先避免它。
我在 VB.net 和 C# 中也有类似的项目,两者都有完全相同的问题。 我对 VB.Net 稍微舒服一些,但我会很高兴以太的答案。
编辑:描述场景以响应评论:
因此,用户将进入并在DGV的新行(例如名称(上填写单元格。 如果他们只填写一行,那么所有内容都会正确更新/插入,数据库会为其分配一个 ID,并在下次访问时显示。 如果他们尝试在每个新行中写入多个列,则会引发并发错误。 我注意到,当他们添加每个新行时,DGV 的 ID 为 DBNull,但是当它被刷新或填充时,它将使用数据库生成的 ID。 当 DGV 在 ID 列中显示正确的键时,它永远不会遇到并发错误。
问题是你的"键列"允许DBNull。 MS 必须具有主键列才能合并记录并防止多次拥有相同的记录。
这里发生的情况是,您的缓存中多次具有相同的记录,当您更新一条记录时,另一条记录不同步。 通过使用单个数据集并将主键应用于每个数据表,可以消除数据的多个副本。当你做类似DataAdapter.Fill((的事情时,MS将合并数据,而不仅仅是盲目地再次添加相同的记录。 然后,当您保存时,它将更新和重置记录上的标志,以便下次保存时,您不会遇到并发错误。
处理并发问题的一种方法是确定脏行。
检查某些内容是否脏的一种方法是在查询期间,您应该获取行的时间戳(即该行具有时间戳列,并且在更新期间此列设置为 getdate(((
现在,在应用程序中进行实际更新之前,您要做的是首先加载您尝试更新的行的时间戳,如果您拥有的行的时间戳与数据库中的时间戳匹配,那么您就知道没有脏行,您可以继续更新。
现在,如果你有一个肮脏的行......你有一些事情要考虑如何处理它......喜欢 - 也许
- 仅更新非脏行
- 停止整个更新过程并重新加载已更新的行,并通知用户这些行已更新。
- 或者允许用户实际覆盖其他用户的数据而不获取他们的更改。
根据您的要求由您决定。