I was under the impression that the OrmLite Save method did an "upsert", update if record/row exist, otherwise insert. In the
- The first thing that looks strange to me is the error message, where it indicates that the value in the PRIMARY field ends with
CoreObjectListPresentation-Pres
, but it does not, it is actually longer than that, the entire value in the Id field isPresentationWorker.Presentations.CoreObjectListPresentation-PresentationWorkerModule:TED-RYZEN:37576
The Id prop in the POCO being saved is however the same as already existing in db:
and db:
I would like to understand how I can get the error, if it is supposed to do an Update
if there already is a PRIMARY KEY with the same value? But as I enabled the logging feature, I can see that the SQL query is actually an INSERT, not an 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
I am considering some form of race condition, but I am not sure how exactly this happens. I tried finding SaveAsync in the source code, but have not found the relevant code for it.
Is there perhaps an improvement for OrmLite to use the INSERT ON DUPLICATE KEY UPDATE
approach when Save methods are used for MySQL?
(Using ServiceStack 5.13.1, .NET5, VS2022, MySqlConnector and db is MySQL8)
CodePudding user response:
OrmLite has to check if the record exists before it decides whether a db.Save*
should either insert or update the record. This leaves room for the possibility that if 2 requests tried to concurrently save the same new record at the same there could be a race condition should the first insert occur just after the second requests check.
Typically this is the result of a double posting bug firing off 2 concurrent requests. Changing it to use explicit db.Insert*
and db.Update*
wont help since you'll get the same response with 2 inserts.
The proper way to handle this is to use the native upsert functionality in each RDBMS which OrmLite doesn't support yet, please vote for the feature request to get notified when the feature is implemented.