Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/github/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
更新访问表时发生VB.NET并发冲突错误_Vb.net - Fatal编程技术网

更新访问表时发生VB.NET并发冲突错误

更新访问表时发生VB.NET并发冲突错误,vb.net,Vb.net,为了消除这个问题,我创建了一个简单的例子来重现这个问题。 在MSaccess数据库中,我有一个名为“tblTest”的表,其中有一个自动递增字段“ID”和一个名为“Test”的字符串字段。ID是主键 下面是代码: Dim cmdSELECT As New OleDbCommand() Dim cmdUPDATE As New OleDbCommand() Dim Para As OleDbParameter Para = New

为了消除这个问题,我创建了一个简单的例子来重现这个问题。 在MSaccess数据库中,我有一个名为“tblTest”的表,其中有一个自动递增字段“ID”和一个名为“Test”的字符串字段。ID是主键

下面是代码:

        Dim cmdSELECT As New OleDbCommand()
        Dim cmdUPDATE As New OleDbCommand()

        Dim Para As OleDbParameter
        Para = New OleDbParameter()
        Para.ParameterName = "@ID"
        Para.OleDbType = OleDbType.Integer
        Para.SourceColumn = "ID"
        cmdUPDATE.Parameters.Add(Para)

        Para = New OleDbParameter()
        Para.ParameterName = "@Test"
        Para.OleDbType = OleDbType.VarChar
        Para.Size = 255
        Para.SourceColumn = "Test"
        cmdUPDATE.Parameters.Add(Para)

        Dim MyConnection As New OleDbConnection
        MyConnection.ConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0; Data Source=" & AddSlash(Application.StartupPath) & "Connexis.accdb"
        MyConnection.Open()

        cmdSELECT.CommandText = "SELECT * FROM tblTest"
        cmdSELECT.Connection = MyConnection
        cmdUPDATE.CommandText = "UPDATE tblTest SET Test = @Test WHERE ID = @ID"
        cmdUPDATE.Connection = MyConnection

        Dim adapter As OleDbDataAdapter = New OleDbDataAdapter()
        adapter.SelectCommand = cmdSELECT
        adapter.UpdateCommand = cmdUPDATE

        Dim DTtest As New DataTable
        adapter.Fill(DTtest)
        DTtest(0)("Test") = "Testing 123"

        adapter.Update(DTtest)
最后一行给出了错误:System.Data.dll中发生了类型为“System.Data.DBConcurrencyException”的第一次意外异常

当我以类似的方式插入时,一切都很好。 当然,从来没有其他用户这样做过。 我错过了什么

关于这个错误已经写了很多,但是我还没有找到答案


谢谢

问题在于,在使用Jet或ACE OLE DB提供程序时,参数是根据其位置使用的。您当然可以指定参数名称,但这些名称不用于将参数与SQL代码中的占位符相匹配。这意味着您必须将参数添加到
OleDbCommand
,添加顺序与它们在SQL代码中出现的顺序相同,但您不能这样做<代码>@Test出现在SQL代码中的
@ID
之前,因此您需要更改:

Dim Para As OleDbParameter
Para = New OleDbParameter()
Para.ParameterName = "@ID"
Para.OleDbType = OleDbType.Integer
Para.SourceColumn = "ID"
cmdUPDATE.Parameters.Add(Para)

Para = New OleDbParameter()
Para.ParameterName = "@Test"
Para.OleDbType = OleDbType.VarChar
Para.Size = 255
Para.SourceColumn = "Test"
cmdUPDATE.Parameters.Add(Para)
为此:

Para = New OleDbParameter()
Para.ParameterName = "@Test"
Para.OleDbType = OleDbType.VarChar
Para.Size = 255
Para.SourceColumn = "Test"
cmdUPDATE.Parameters.Add(Para)

Dim Para As OleDbParameter
Para = New OleDbParameter()
Para.ParameterName = "@ID"
Para.OleDbType = OleDbType.Integer
Para.SourceColumn = "ID"
cmdUPDATE.Parameters.Add(Para)
实际上,为了避免编写不必要的复杂代码,您应该将其更改为:

cmdUPDATE.Parameters.Add("@Test", OleDbType.VarChar, 255, "Test")
cmdUPDATE.Parameters.Add("@ID", OleDbType.Integer, 0, "ID")
编辑:

我还应该指出这会产生并发冲突的确切原因。并发异常有一个特定的合法目的:检测保存当前用户的更改会与另一用户同时所做的更改发生冲突的情况

考虑这样一种情况:用户a检索数据,然后用户B检索相同的数据。用户B对记录中的第1列进行更改,然后保存更改。用户A对同一记录中的第2列进行更改,然后尝试保存更改。在“wins中的最后一个”场景中,将保存用户a的数据,这将用用户a保存的记录中的原始值替换用户B保存的第1列中的新值,从而删除用户B的更改。我的大多数人都认为那是不好的

使用“乐观并发”,当用户A尝试保存其更改时,系统将保存的记录的原始数据与数据库中当前的数据进行比较。如果它们匹配,则其他用户未进行任何更改,这些更改将被保存。如果它们不匹配,将发生并发冲突,ADO.NET将抛出异常。作为开发人员,捕获该异常并执行适当的操作取决于您。这通常意味着检索数据库中当前的数据,或者用该数据替换现有的数据,或者将两者合并。然后,用户应该再次查看数据,做出任何他们认为合适的附加更改,然后再次保存。 该方法被称为“乐观并发”的原因是它希望最好,即允许用户同时检索和使用相同的数据,但计划最坏的情况,即确保对该数据的多个更改不会相互干扰。第三个选项是“悲观并发”,它假设最坏的情况,并且不允许多个用户首先检索相同的数据。这通常是使用行级或表级锁完成的