/// <summary>
        /// Performs a pessimistic lock upgrade on a given entity, if needed.
        /// </summary>
        /// <param name="entity">The entity for which to upgrade the lock.</param>
        /// <param name="entry">The entity's EntityEntry instance.</param>
        /// <param name="requestedLockMode">The lock mode being requested for locking. </param>
        /// <param name="source">The session which is the source of the event being processed.</param>
        /// <param name="cancellationToken">A cancellation token that can be used to cancel the work</param>
        protected virtual async Task UpgradeLockAsync(object entity, EntityEntry entry, LockMode requestedLockMode, ISessionImplementor source, CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();
            if (requestedLockMode.GreaterThan(entry.LockMode))
            {
                // The user requested a "greater" (i.e. more restrictive) form of
                // pessimistic lock
                if (entry.Status != Status.Loaded)
                {
                    throw new ObjectDeletedException("attempted to lock a deleted instance", entry.Id, entry.EntityName);
                }

                IEntityPersister persister = entry.Persister;

                if (log.IsDebugEnabled())
                {
                    log.Debug("locking {0} in mode: {1}", MessageHelper.InfoString(persister, entry.Id, source.Factory), requestedLockMode);
                }

                ISoftLock slock;
                CacheKey  ck;
                if (persister.HasCache)
                {
                    ck    = source.GenerateCacheKey(entry.Id, persister.IdentifierType, persister.RootEntityName);
                    slock = await(persister.Cache.LockAsync(ck, entry.Version, cancellationToken)).ConfigureAwait(false);
                }
                else
                {
                    ck    = null;
                    slock = null;
                }

                try
                {
                    if (persister.IsVersioned && requestedLockMode == LockMode.Force)
                    {
                        // todo : should we check the current isolation mode explicitly?
                        object nextVersion = await(persister.ForceVersionIncrementAsync(entry.Id, entry.Version, source, cancellationToken)).ConfigureAwait(false);
                        entry.ForceLocked(entity, nextVersion);
                    }
                    else
                    {
                        await(persister.LockAsync(entry.Id, entry.Version, entity, requestedLockMode, source, cancellationToken)).ConfigureAwait(false);
                    }
                    entry.LockMode = requestedLockMode;
                }
                finally
                {
                    // the database now holds a lock + the object is flushed from the cache,
                    // so release the soft lock
                    if (persister.HasCache)
                    {
                        await(persister.Cache.ReleaseAsync(ck, slock, cancellationToken)).ConfigureAwait(false);
                    }
                }
            }
        }