首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >当通过MySQL链接数据集通过TableAdapters使用时,什么会导致并发冲突?

当通过MySQL链接数据集通过TableAdapters使用时,什么会导致并发冲突?
EN

Stack Overflow用户
提问于 2021-05-25 20:20:02
回答 2查看 406关注 0票数 1

我读得越多,就越困惑,所以希望有人能帮上忙。我有一个复杂的数据库设置,有时会在更新时产生错误:

“并发冲突: UpdateCommand影响了预期的1条记录中的0条”

我有时会说,因为我不能重新创造条件来持续地触发它。我有一个远程mySQL数据库,通过DataSource向导连接到我的应用程序,该向导生成数据集、表和链接的DataTableAdapters。

我的阅读表明,当试图更新同一记录的数据库有多个打开连接时,就会发生此错误?这不应该发生在我的例子,因为唯一的更新是从我的应用程序顺序。

我想知道这是否与从后台工作人员运行更新有关?例如,我把我的表更新放在一个中:

代码语言:javascript
复制
    Gi_gamethemeTableAdapter.Update(dbDS.gi_gametheme)
    Gi_gameplaystyleTableAdapter.Update(dbDS.gi_gameplaystyle)
    Gi_gameTableAdapter.Update(dbDS.gi_game)

然而,这些程序在后台工作人员中连续运行,因此对此不确定。主线程也在等待它完成,在启动之前或之后没有其他的db操作。

我读过有关进入dataset designer视图的文章,在datatableadapter > advanced中选择“配置”,并将“使用乐观并发性”设置为false。这可能是可行的(很难说,因为错误看起来是随机的),但是,我想要避免的缺点是:

  1. 我有大约60张桌子。我不想对每个人都这么做。
  2. 有时,我不得不将mysql模式重新导入dataset designer,或者删除一个表并重新添加它。这显然会失去这个设置,我将不得不记住,再次对所有的设置,有可能。我也无法在代码中找到一种自动完成此操作的方法。

在数据库更新等方面,我恐怕不是在代码级别,而是依赖于Visual向导。更改堆栈也为时已晚(例如无法更改为实体框架等)。

所以我的问题是:

  1. 什么是/如何找到导致错误的原因?
  2. 我能做些什么?

谢谢

EN

回答 2

Stack Overflow用户

发布于 2021-05-25 20:42:12

当您有将数据下载到数据中的tableadapters时,可以将它们配置为乐观并发。

这意味着对于像以下这样的桌子:

代码语言:javascript
复制
Person
ID  Name
1   John

它们可能会生成一个更新查询,例如:

代码语言:javascript
复制
UPDATE Person SET Name = @newName WHERE ID = @oldID AND Name = @oldName

(实际上,它们比这更复杂,但这就足够了)

Datatable跟踪原始值和当前值;您下载1/ "John“,然后将名称更改为"Jane",您(或tableadapter)可以问DT原始值是什么,它会说”John“。

datatable还可以将此值输入更新查询,这就是我们如何检测“如果有其他什么东西在我们拥有时更改了行”,即并发冲突。

当我们下载时,行是"John“,我们把它编辑成"Jane",然后去保存。但是其他人也加入了,并把它改成了“乔”。我们的更新将失败,因为当我们下载它时,名称不再是"John“(而且我们仍然认为它是)。使用具有AND Name = @oldName的更新查询的tableadapter,并将@oldName参数设置为原始值somedatarow["Name", DataRowVersion.Original].Value (即“约翰”)我们导致更新失败。这是一件有用的事情;大多数情况下他们会成功,因此我们可以机会主义地希望我们的用户能够更新我们的db,而不需要在某些UI中打开行时进入锁定行。

解决不起作用的情况通常是编写某种策略的案例:

  • 我的更改获胜--不要使用带有旧值的乐观查询,只需更新和删除它们的更改即可。
  • 他们的改变赢了-取消你的尝试
  • 重新下载最新的DB状态并选择做什么--以某种方式自动合并它(可能是其他人更改了您没有更改的字段),或者向用户显示,这样他们就可以选择保留什么等等(如果两个人都编辑了相同的字段)

现在你可能坐在那里说“但是没有其他人改变我的数据库”--不过,如果数据库在一次保存中更改了一些值,而且数据集中没有最新的值,我们仍然可以得到它。

tableadapter wizardd中还有另一个选项--“刷新数据集”--它应该在修改后运行一个select,以导入任何最新的数据库计算值(比如auto主键或触发器/默认值/等等)。有些查询(如INSERT INTO Person(Name) VALUES(@name) )应该在其末尾单独标记一个SELECT * FROM PERSON WHERE ID = last_inserted_id(),以检索最新的值。

除了“刷新数据集”无效 :/

所以,虽然我不能确切地告诉你为什么会得到你的简历异常,但我希望解释它们的原因,并指出有时会有错误导致它们(插入新记录,计算出的ID不会被撤回,编辑最近的记录,更新失败,因为数据不是新鲜的),希望能为您提供找到问题所需的武器:当您得到一个问题时,保持应用程序在断点上停止并检查数据仓库:查看正在运行的查询,查看正在作为参数的原始/当前值-使用允许您声明所需版本的项索引器的重载。检查该行持有的原始值和当前值,并查看DB。

所有这些都会有不匹配的地方,从而解释了为什么更新了0条记录??数据库以"Joe“作为名称,174354325作为ID,您的数据方式将"John”作为原始名称,-1作为ID (它从未刷新),因此WHERE子句找到了0条记录。

票数 1
EN

Stack Overflow用户

发布于 2021-05-25 20:41:34

有些表将包含一个标记为[ConcurrencyCheck][TimeStamp] 并发令牌的字段。

更新记录时,生成的SQL将包括一个WHERE [ConcurrencyField]='Whatever the value was when the record was retrieved'

如果该记录是由另一个线程或进程或当前线程以外的其他内容更新的,那么您的更新将返回0条更新的记录,而不是预期的1(或更多)记录。

看你怎么办?首先,在代码周围放置一个尝试/捕获(DbConcurrencyException)。然后,您可以重新读取违规记录,并尝试再次更新它。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67695121

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档