I'm using MongoDB with the .NET driver and trying to implement an optimistic concurrency pattern with versioning using UpdateOneAsync and IsUpsert = true.
Here is my code:
public Task UpsertAsync(User user, CancellationToken cancellationToken) =>
context.Users.UpdateOneAsync(
Builders<User>.Filter.Eq(u => u.Id, user.Id) &
Builders<User>.Filter.Lt(u => u.Version, user.Version),
Builders<User>.Update
.SetOnInsert(u => u.Id, user.Id)
.Set(u => u.IsDeleted, user.IsDeleted)
.Set(u => u.Version, user.Version)
.Set(u => u.Name, user.Name)
.Set(u => u.UserName, user.UserName)
.Set(u => u.Media, user.Media),
new UpdateOptions { IsUpsert = true },
cancellationToken
);
Goal
Insert the document if it does not exist
Update it only if the incoming
Versionis greater than the stored one
Problem
When a document already exists with a higher version, the filter does not match:
Id == user.Id AND Version < user.Version → false
Because of IsUpsert = true, MongoDB attempts to insert a new document, which leads to:
DuplicateKeyException (same Id)
Question
What is the recommended way to handle this scenario?
Is catching and ignoring
DuplicateKeyExceptionthe correct/expected approach in this pattern?Or is there a better way to implement "update only if version is newer, otherwise do nothing" without triggering an insert attempt?
I'm trying to keep this operation atomic and avoid race conditions, so I'd prefer a single-query solution if possible.
Any guidance or best practices would be appreciated.