Concurrent Editing
LightSpeed uses optimistic concurrency: that is, it allows users to edit an entity without taking a lock, optimistically assuming that it is okay for users to edit the same entity at the same time. When each user commits their changes, their version of the entity is persisted. LightSpeed doesn’t check whether there has been a concurrent edit. This is effectively a ‘last one wins’ policy.
LightSpeed also supports concurrency checking, which results in an exception being thrown if a user tries to save an entity when that entity has been modified since the user first loaded it. This is effectively a ‘first one wins’ policy.
To enable concurrency checking for entities of a particular type, select the entity and set Optimistic Concurrency Checking to true.
The Optimistic Concurrency Checking option creates a field named LockVersion. LightSpeed automatically increments this field each time the entity is saved, and verifies that the version of the entity in the database is still the version that was originally loaded. If not, it means that somebody else has changed the entity in the meantime, and LightSpeed raises an OptimisticConcurrencyException.
The database must contain the corresponding backing column for the LockVersion field. If you use Update Database or Create Migration in the designer, it will create this column for you. If you create the column manually, it must be a non-nullable column of integer type.
Guidance for Optimistic Concurrency Checking
If a concurrency check fails, LightSpeed raises an OptimisticConcurrencyException. However, the exception does not indicate which entity the error relates to. You should therefore normally use optimistic concurrency checking only in scenarios where users will be editing one entity at a time. If you must allow batch editing, then if an exception occurs you will need to query the database to figure out which entities have changed and are causing the error.
LightSpeed does not provide a way to revert entities or merge changes. To resolve an OptimisticConcurrencyException, you will typically need to load the latest versions of the entities you want to save into a fresh unit of work, and merge the changes from the stale unit of work (where the original edits took place) into the fresh unit of work. You can use entity property change tracking and the metadata API to help with this.