Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

Optimistic locking is favorable for smallish objects.
However, for larger objects, optimistic locking poses
a problem. A user might invest a lot of work into
modifying an object before learning that he cannot
save his work, because he lost the race for committing
first. Fortunately, adding pessimistic
locking to the optimistic locking at hand is possible.

Manipulating time-stamps does NOT work

A naive approach is to manipulate the timestamps of
a loaded object in such a fashion that it looks as
if it had been written immediately after loading.
This does not work, however, because subsequent loads
will not be impressed by the time-stamp. Other users
can read and write the object to their hearts' content,
and the user with the original load will have difficulties
saving his modifications. This is NOT pessimistic locking.

Method 1: extra flag, extra storage provider

The most obvious route to pessimistic locking is an extra
field (flag) in the lockable domain object. Upon load
(DomainObject.OnLoaded method), the flag is set and subsequent
modifications are impossible if that flag is set. In theory, checking
the flag could be done by the application, i.e. some layer supertype
with appropriate overloads of DomainObject.OnLoaded. Keep in
mind, however, that the object you want to load (and lock)
might be loaded in the course of a transaction that has
already modified other objects. Since you can't commit
single objects, only transactions, a commit for writing
the lock field will commit the modifications for all the
other objects. This is not desirable. Opening the object in
another root-transaction for writing the lock is not possible either,
because at the time your overridden OnLoaded is invoked, your object
is part of a sub-transaction already. Trying to load it
into another root transaction will give you a concurrency
violation exception.

The correct approach is to leave locking
and monitoring the lock to the storage provider. If you
want to go the route with the extra flag, write your own
storage provider for the objects you want to lock pessimistically.
With your dedicated storage provider, locking is fairly
easy. In your storage provider you CAN override the loader
in such a fashion that it updates and checks your locked
flag.

Method 2: lock objects

A simpler, but more expensive method is to provide extra lock objects
for the domain objects you want to lock pessimistically.
Such domain objects contain a reference property to the
lock object, also a domain object. If the lock object
(i.e. a property in it) is set to true, no modifications
are possible.

In contrast to the object you want to lock, the lock
object is never loaded for anything other than maintaining
the flag. It is never loaded implicitely. The lock object attached
to a particular domain object CAN be loaded into its own root transaction
and committed without affecting other objects. This
method does not require a special storage provider, and
is probably less work and easier to use. However, the
extra GetObject() and Commit() round-trip is more
expensive than maintaining and monitoring the flag data in a
dedicated storage provider – the method preferred by
the ECMS team, by the way.DELETE ME