Optimistic Concurrency Control

From Bitnami MediaWiki
Revision as of 18:43, 5 October 2023 by User (talk | contribs)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

See also the Database section for the audit fields.

Add Version property e.g. public int? Version { get; set; } in the entity. Create a partial class for the entity in the Novus.Model.Entity.PartialEntities namespace and implement the following interface:

public partial class Foo : OptimisticConcurrencyControl

Disconnected update.

dbContext.Entry(foo)
  .Property("Version").OriginalValue = foo.Version;
foo.Version++;

// detaching existing entity prevents InvalidOperationException on save dbContext.Entry(existingFoo).State = EntityState.Detached;

dbContext.Foo.Update(foo);

In this situation, the foo variable is the incoming data while existingFoo is the existing entity fetched from the database in the current transaction.

DTO style:

dbContext.Entry(entity)
  .Property("Version").OriginalValue = dto.Version;
entity.Version++;

In the case of a DTO, only some of the entity's properties are updated.

Catch exception on save:

try
{
  await dbContext.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
  result.Message = $"Record was already updated by another transaction. Please refresh and try again.";
  result.ResultStatus = ResultStatus.Failure;
  return result;
} 

BaseService helper method. With the entity implementing the OptimisticConcurrencyControl interface, call the IncrementVersion(dbContext, existingEntity) for entities fetched in the current transaction that will be updated in the same transaction. For disconnected updates, call IncrementVersion(dbContext, existingEntity, disconnectedEntity.Version) by passing in the version from the front end.


Return to Programming Guide