ServiceStack OrmLite:.Save/SaveAsync 在主键上生成重复条目
ServiceStack OrmLite: .Save/SaveAsync generates Duplicate entry on PRIMARY key
我的印象是 OrmLite Save 方法进行了“更新插入”,如果 record/row 存在则更新,否则插入。
在 documentation for ServiceStack OrmLite 中,它表示:
Save and SaveAll will Insert if no record with Id exists, otherwise it Updates.
但是,有时我会收到重复输入错误:
Duplicate entry 'PresentationWorker.Presentations.CoreObjectListPresentation-Pres' for key 'presentationproducer.PRIMARY
POCO 有一个 Id
属性 即 PrimaryKey
[PrimaryKey]
[StringLength(512)]
public string Id { get; set; }
此外,MySQL 中的数据库有 Id
作为主键:
- 首先让我觉得奇怪的是错误信息,它表明PRIMARY字段中的值以
CoreObjectListPresentation-Pres
结尾,但它不是,它实际上比那个长,整个Id 字段中的值为 PresentationWorker.Presentations.CoreObjectListPresentation-PresentationWorkerModule:TED-RYZEN:37576
正在保存的 POCO 中的 Id 道具与数据库中已有的相同:
和数据库:
我想知道如果已经有一个具有相同值的 PRIMARY KEY 应该执行 Update
,我是如何得到错误的?但是当我启用日志记录功能时,我可以看到 SQL 查询实际上是一个 INSERT,而不是 UPDATE:
SQL: INSERT INTO PresentationProducer
(Id
,PresentationType
,ModuleChannelName
,LastUpdatedTimestamp
)
VALUES
(@Id,@PresentationType,@ModuleChannelName,@LastUpdatedTimestamp)
PARAMS:
@Id=PresentationWorker.Presentations.CoreObjectListPresentation-PresentationWorkerModule:TED-RYZEN:37576,
@PresentationType=PresentationWorker.Presentations.CoreObjectListPresentation,
@ModuleChannelName=PresentationWorkerModule:TED-RYZEN:37576,
@LastUpdatedTimestamp=2021-11-21 09:09:02
我正在考虑某种形式的竞争条件,但我不确定这到底是怎么发生的。我试图在源代码中找到 SaveAsync,但没有找到它的相关代码。
当 Save 方法用于 MySQL 时,OrmLite 是否可以使用 INSERT ON DUPLICATE KEY UPDATE
方法进行改进?
(使用 ServiceStack 5.13.1、.NET5、VS2022、MySqlConnector 和数据库为 MySQL8)
OrmLite 在决定 db.Save*
是否应该插入或更新记录之前必须检查记录是否存在。这为以下可能性留下了空间:如果 2 个请求同时尝试同时保存相同的新记录,则如果第一个插入发生在第二个请求检查之后,则可能会出现竞争条件。
这通常是双重发布错误触发 2+ 个并发请求的结果。将其更改为使用显式 db.Insert*
和 db.Update*
不会有帮助,因为您将获得与 2+ 插入相同的响应。
处理此问题的正确方法是在 OrmLite 尚不支持的每个 RDBMS 中使用本机更新插入功能,请vote for the feature request在实现该功能时收到通知。
我的印象是 OrmLite Save 方法进行了“更新插入”,如果 record/row 存在则更新,否则插入。 在 documentation for ServiceStack OrmLite 中,它表示:
Save and SaveAll will Insert if no record with Id exists, otherwise it Updates.
但是,有时我会收到重复输入错误:
Duplicate entry 'PresentationWorker.Presentations.CoreObjectListPresentation-Pres' for key 'presentationproducer.PRIMARY
POCO 有一个 Id
属性 即 PrimaryKey
[PrimaryKey]
[StringLength(512)]
public string Id { get; set; }
此外,MySQL 中的数据库有 Id
作为主键:
- 首先让我觉得奇怪的是错误信息,它表明PRIMARY字段中的值以
CoreObjectListPresentation-Pres
结尾,但它不是,它实际上比那个长,整个Id 字段中的值为PresentationWorker.Presentations.CoreObjectListPresentation-PresentationWorkerModule:TED-RYZEN:37576
正在保存的 POCO 中的 Id 道具与数据库中已有的相同:
和数据库:
我想知道如果已经有一个具有相同值的 PRIMARY KEY 应该执行 Update
,我是如何得到错误的?但是当我启用日志记录功能时,我可以看到 SQL 查询实际上是一个 INSERT,而不是 UPDATE:
SQL: INSERT INTO
PresentationProducer
(Id
,PresentationType
,ModuleChannelName
,LastUpdatedTimestamp
) VALUES (@Id,@PresentationType,@ModuleChannelName,@LastUpdatedTimestamp) PARAMS: @Id=PresentationWorker.Presentations.CoreObjectListPresentation-PresentationWorkerModule:TED-RYZEN:37576, @PresentationType=PresentationWorker.Presentations.CoreObjectListPresentation, @ModuleChannelName=PresentationWorkerModule:TED-RYZEN:37576, @LastUpdatedTimestamp=2021-11-21 09:09:02
我正在考虑某种形式的竞争条件,但我不确定这到底是怎么发生的。我试图在源代码中找到 SaveAsync,但没有找到它的相关代码。
当 Save 方法用于 MySQL 时,OrmLite 是否可以使用 INSERT ON DUPLICATE KEY UPDATE
方法进行改进?
(使用 ServiceStack 5.13.1、.NET5、VS2022、MySqlConnector 和数据库为 MySQL8)
OrmLite 在决定 db.Save*
是否应该插入或更新记录之前必须检查记录是否存在。这为以下可能性留下了空间:如果 2 个请求同时尝试同时保存相同的新记录,则如果第一个插入发生在第二个请求检查之后,则可能会出现竞争条件。
这通常是双重发布错误触发 2+ 个并发请求的结果。将其更改为使用显式 db.Insert*
和 db.Update*
不会有帮助,因为您将获得与 2+ 插入相同的响应。
处理此问题的正确方法是在 OrmLite 尚不支持的每个 RDBMS 中使用本机更新插入功能,请vote for the feature request在实现该功能时收到通知。