Beispiel #1
0
        protected virtual void PerformUpdate(SaveOrUpdateEvent @event, object entity, IEntityPersister persister)
        {
            if (!persister.IsMutable)
            {
                log.Debug("immutable instance passed to PerformUpdate(), locking");
            }

            if (log.IsDebugEnabled())
            {
                log.Debug("updating {0}", MessageHelper.InfoString(persister, @event.RequestedId, @event.Session.Factory));
            }

            IEventSource source = @event.Session;

            EntityKey key = source.GenerateEntityKey(@event.RequestedId, persister);

            source.PersistenceContext.CheckUniqueness(key, entity);

            if (InvokeUpdateLifecycle(entity, persister, source))
            {
                Reassociate(@event, @event.Entity, @event.RequestedId, persister);
                return;
            }

            // this is a transient object with existing persistent state not loaded by the session
            new OnUpdateVisitor(source, @event.RequestedId, entity).Process(entity, persister);

            //TODO: put this stuff back in to read snapshot from
            //      the second-level cache (needs some extra work)

            /*Object[] cachedState = null;
             *
             * if ( persister.hasCache() ) {
             * CacheEntry entry = (CacheEntry) persister.getCache()
             * .get( event.getRequestedId(), source.getTimestamp() );
             * cachedState = entry==null ?
             * null :
             * entry.getState(); //TODO: half-assemble this stuff
             * }*/

            source.PersistenceContext.AddEntity(
                entity,
                persister.IsMutable ? Status.Loaded : Status.ReadOnly,
                null,
                key,
                persister.GetVersion(entity),
                LockMode.None,
                true,
                persister,
                false);

            //persister.AfterReassociate(entity, source); TODO H3.2 not ported

            if (log.IsDebugEnabled())
            {
                log.Debug("updating {0}", MessageHelper.InfoString(persister, @event.RequestedId, source.Factory));
            }

            CascadeOnUpdate(@event, persister, entity);
        }
Beispiel #2
0
 /// <summary> Delete a entity. </summary>
 /// <param name="entityName">The entityName for the entity to be deleted </param>
 /// <param name="entity">a detached entity instance </param>
 public void Delete(string entityName, object entity)
 {
     using (BeginProcess())
     {
         IEntityPersister persister = GetEntityPersister(entityName, entity);
         object           id        = persister.GetIdentifier(entity);
         object           version   = persister.GetVersion(entity);
         persister.Delete(id, version, entity, this);
     }
 }
Beispiel #3
0
 /// <summary> Delete a entity. </summary>
 /// <param name="entityName">The entityName for the entity to be deleted </param>
 /// <param name="entity">a detached entity instance </param>
 public void Delete(string entityName, object entity)
 {
     using (new SessionIdLoggingContext(SessionId))
     {
         CheckAndUpdateSessionStatus();
         IEntityPersister persister = GetEntityPersister(entityName, entity);
         object           id        = persister.GetIdentifier(entity);
         object           version   = persister.GetVersion(entity);
         persister.Delete(id, version, entity, this);
     }
 }
Beispiel #4
0
 /// <summary> Delete a entity. </summary>
 /// <param name="entityName">The entityName for the entity to be deleted </param>
 /// <param name="entity">a detached entity instance </param>
 /// <param name="cancellationToken">A cancellation token that can be used to cancel the work</param>
 public async Task DeleteAsync(string entityName, object entity, CancellationToken cancellationToken = default(CancellationToken))
 {
     cancellationToken.ThrowIfCancellationRequested();
     using (BeginProcess())
     {
         IEntityPersister persister = GetEntityPersister(entityName, entity);
         object           id        = persister.GetIdentifier(entity);
         object           version   = persister.GetVersion(entity);
         await(persister.DeleteAsync(id, version, entity, this, cancellationToken)).ConfigureAwait(false);
     }
 }
Beispiel #5
0
 /// <summary> Delete a entity. </summary>
 /// <param name="entityName">The entityName for the entity to be deleted </param>
 /// <param name="entity">a detached entity instance </param>
 /// <param name="cancellationToken">A cancellation token that can be used to cancel the work</param>
 public async Task DeleteAsync(string entityName, object entity, CancellationToken cancellationToken = default(CancellationToken))
 {
     cancellationToken.ThrowIfCancellationRequested();
     using (new SessionIdLoggingContext(SessionId))
     {
         CheckAndUpdateSessionStatus();
         IEntityPersister persister = GetEntityPersister(entityName, entity);
         object           id        = persister.GetIdentifier(entity);
         object           version   = persister.GetVersion(entity);
         await(persister.DeleteAsync(id, version, entity, this, cancellationToken)).ConfigureAwait(false);
     }
 }
        public static T Attach <T>(this ISession session, T entity, LockMode mode = null)
        {
            mode = mode ?? LockMode.None;

            IEntityPersister persister = session.GetSessionImplementation().GetEntityPersister(NHibernateProxyHelper.GuessClass(entity).FullName, entity);

            Object[]    fields  = persister.GetPropertyValues(entity, session.ActiveEntityMode);
            Object      id      = persister.GetIdentifier(entity, session.ActiveEntityMode);
            Object      version = persister.GetVersion(entity, session.ActiveEntityMode);
            EntityEntry entry   = session.GetSessionImplementation().PersistenceContext.AddEntry(entity, Status.Loaded, fields, null, id, version, LockMode.None, true, persister, true, false);

            return(entity);
        }
        private static bool IsVersionChanged(object entity, IEventSource source, IEntityPersister persister, object target)
        {
            if (!persister.IsVersioned)
            {
                return(false);
            }
            // for merging of versioned entities, we consider the version having
            // been changed only when:
            // 1) the two version values are different;
            //      *AND*
            // 2) The target actually represents database state!
            //
            // This second condition is a special case which allows
            // an entity to be merged during the same transaction
            // (though during a separate operation) in which it was
            // originally persisted/saved
            bool changed =
                !persister.VersionType.IsSame(persister.GetVersion(target, source.EntityMode),
                                              persister.GetVersion(entity, source.EntityMode), source.EntityMode);

            // TODO : perhaps we should additionally require that the incoming entity
            // version be equivalent to the defined unsaved-value?
            return(changed && ExistsInDatabase(target, source, persister));
        }
Beispiel #8
0
 /// <summary>Update a entity.</summary>
 /// <param name="entityName">The entityName for the entity to be updated </param>
 /// <param name="entity">a detached entity instance </param>
 public void Update(string entityName, object entity)
 {
     using (BeginProcess())
     {
         IEntityPersister persister = GetEntityPersister(entityName, entity);
         object           id        = persister.GetIdentifier(entity);
         object[]         state     = persister.GetPropertyValues(entity);
         object           oldVersion;
         if (persister.IsVersioned)
         {
             oldVersion = persister.GetVersion(entity);
             object newVersion = Versioning.Increment(oldVersion, persister.VersionType, this);
             Versioning.SetVersion(state, newVersion, persister);
             persister.SetPropertyValues(entity, state);
         }
         else
         {
             oldVersion = null;
         }
         persister.Update(id, state, null, false, null, oldVersion, entity, null, this);
     }
 }
Beispiel #9
0
        /// <summary>
        /// Called on flush dirty entity.
        /// </summary>
        /// <param name="entity">The entity.</param>
        /// <param name="id">The id.</param>
        /// <param name="currentState">State of the current.</param>
        /// <param name="previousState">State of the previous.</param>
        /// <param name="propertyNames">The property names.</param>
        /// <param name="types">The types.</param>
        /// <returns>True if object is dirty and should be flashed.</returns>
        /// <exception cref="NHibernate.StaleObjectStateException">The stale object state exception.</exception>
        public override bool OnFlushDirty(object entity, object id, object[] currentState, object[] previousState, string[] propertyNames, NHibernate.Type.IType[] types)
        {
            ISessionImplementor sessionImplementation = session.GetSessionImplementation();
            IPersistenceContext persistenceContext    = sessionImplementation.PersistenceContext;
            EntityEntry         entityEntry           = persistenceContext.GetEntry(entity);
            IEntityPersister    persister             = entityEntry.Persister;

            if (persister.IsVersioned && entityEntry.ExistsInDatabase)
            {
                EntityMode mode = session.GetSessionImplementation().EntityMode;

                object version        = persister.GetVersion(entity, mode);
                object currentVersion = persister.GetCurrentVersion(id, sessionImplementation);

                if (!persister.VersionType.IsEqual(currentVersion, version))
                {
                    throw new ConcurrentDataException((Entity)entity);
                }
            }

            return(base.OnFlushDirty(entity, id, currentState, previousState, propertyNames, types));
        }
 /// <summary>Update a entity.</summary>
 /// <param name="entityName">The entityName for the entity to be updated </param>
 /// <param name="entity">a detached entity instance </param>
 public void Update(string entityName, object entity)
 {
     using (new SessionIdLoggingContext(SessionId))
     {
         CheckAndUpdateSessionStatus();
         IEntityPersister persister = GetEntityPersister(entityName, entity);
         object           id        = persister.GetIdentifier(entity, EntityMode.Poco);
         object[]         state     = persister.GetPropertyValues(entity, EntityMode.Poco);
         object           oldVersion;
         if (persister.IsVersioned)
         {
             oldVersion = persister.GetVersion(entity, EntityMode.Poco);
             object newVersion = Versioning.Increment(oldVersion, persister.VersionType, this);
             Versioning.SetVersion(state, newVersion, persister);
             persister.SetPropertyValues(entity, state, EntityMode.Poco);
         }
         else
         {
             oldVersion = null;
         }
         persister.Update(id, state, null, false, null, oldVersion, entity, null, this);
     }
 }
Beispiel #11
0
 /// <summary>Update a entity.</summary>
 /// <param name="entityName">The entityName for the entity to be updated </param>
 /// <param name="entity">a detached entity instance </param>
 /// <param name="cancellationToken">A cancellation token that can be used to cancel the work</param>
 public async Task UpdateAsync(string entityName, object entity, CancellationToken cancellationToken = default(CancellationToken))
 {
     cancellationToken.ThrowIfCancellationRequested();
     using (BeginProcess())
     {
         IEntityPersister persister = GetEntityPersister(entityName, entity);
         object           id        = persister.GetIdentifier(entity);
         object[]         state     = persister.GetPropertyValues(entity);
         object           oldVersion;
         if (persister.IsVersioned)
         {
             oldVersion = persister.GetVersion(entity);
             object newVersion = await(Versioning.IncrementAsync(oldVersion, persister.VersionType, this, cancellationToken)).ConfigureAwait(false);
             Versioning.SetVersion(state, newVersion, persister);
             persister.SetPropertyValues(entity, state);
         }
         else
         {
             oldVersion = null;
         }
         await(persister.UpdateAsync(id, state, null, false, null, oldVersion, entity, null, this, cancellationToken)).ConfigureAwait(false);
     }
 }
        public override void Execute()
        {
            object              id        = Id;
            IEntityPersister    persister = Persister;
            ISessionImplementor session   = Session;
            object              instance  = Instance;

            bool      statsEnabled = Session.Factory.Statistics.IsStatisticsEnabled;
            Stopwatch stopwatch    = null;

            if (statsEnabled)
            {
                stopwatch = Stopwatch.StartNew();
            }

            bool veto = PreDelete();

            object tmpVersion = version;

            if (persister.IsVersionPropertyGenerated)
            {
                // we need to grab the version value from the entity, otherwise
                // we have issues with generated-version entities that may have
                // multiple actions queued during the same flush
                tmpVersion = persister.GetVersion(instance, session.EntityMode);
            }

            CacheKey ck;

            if (persister.HasCache)
            {
                ck    = new CacheKey(id, persister.IdentifierType, persister.RootEntityName, session.EntityMode, session.Factory);
                sLock = persister.Cache.Lock(ck, version);
            }
            else
            {
                ck = null;
            }

            if (!isCascadeDeleteEnabled && !veto)
            {
                persister.Delete(id, tmpVersion, instance, session);
            }

            //postDelete:
            // After actually deleting a row, record the fact that the instance no longer
            // exists on the database (needed for identity-column key generation), and
            // remove it from the session cache
            IPersistenceContext persistenceContext = session.PersistenceContext;

            EntityEntry entry = persistenceContext.RemoveEntry(instance);

            if (entry == null)
            {
                throw new AssertionFailure("Possible nonthreadsafe access to session");
            }
            entry.PostDelete();

            EntityKey key = new EntityKey(entry.Id, entry.Persister, session.EntityMode);

            persistenceContext.RemoveEntity(key);
            persistenceContext.RemoveProxy(key);

            if (persister.HasCache)
            {
                persister.Cache.Evict(ck);
            }

            PostDelete();

            if (statsEnabled && !veto)
            {
                stopwatch.Stop();
                Session.Factory.StatisticsImplementor.DeleteEntity(Persister.EntityName, stopwatch.Elapsed);
            }
        }
        public virtual async Task OnReplicateAsync(ReplicateEvent @event, CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();
            IEventSource source = @event.Session;

            if (source.PersistenceContext.ReassociateIfUninitializedProxy(@event.Entity))
            {
                log.Debug("uninitialized proxy passed to replicate()");
                return;
            }

            object entity = await(source.PersistenceContext.UnproxyAndReassociateAsync(@event.Entity, cancellationToken)).ConfigureAwait(false);

            if (source.PersistenceContext.IsEntryFor(entity))
            {
                log.Debug("ignoring persistent instance passed to replicate()");
                //hum ... should we cascade anyway? throw an exception? fine like it is?
                return;
            }

            IEntityPersister persister = source.GetEntityPersister(@event.EntityName, entity);

            // get the id from the object

            /*if ( persister.isUnsaved(entity, source) ) {
             * throw new TransientObjectException("transient instance passed to replicate()");
             * }*/
            object id = persister.GetIdentifier(entity);

            if (id == null)
            {
                throw new TransientObjectException("instance with null id passed to replicate()");
            }

            ReplicationMode replicationMode = @event.ReplicationMode;
            object          oldVersion;

            if (replicationMode == ReplicationMode.Exception)
            {
                //always do an INSERT, and let it fail by constraint violation
                oldVersion = null;
            }
            else
            {
                //what is the version on the database?
                oldVersion = await(persister.GetCurrentVersionAsync(id, source, cancellationToken)).ConfigureAwait(false);
            }

            if (oldVersion != null)
            {
                if (log.IsDebugEnabled())
                {
                    log.Debug("found existing row for {0}", MessageHelper.InfoString(persister, id, source.Factory));
                }

                // HHH-2378
                object realOldVersion = persister.IsVersioned ? oldVersion : null;

                bool canReplicate =
                    replicationMode.ShouldOverwriteCurrentVersion(entity, realOldVersion,
                                                                  persister.GetVersion(entity),
                                                                  persister.VersionType);

                if (canReplicate)
                {
                    //will result in a SQL UPDATE:
                    await(PerformReplicationAsync(entity, id, realOldVersion, persister, replicationMode, source, cancellationToken)).ConfigureAwait(false);
                }
                else
                {
                    //else do nothing (don't even reassociate object!)
                    log.Debug("no need to replicate");
                }

                //TODO: would it be better to do a refresh from db?
            }
            else
            {
                // no existing row - do an insert
                if (log.IsDebugEnabled())
                {
                    log.Debug("no existing row, replicating new instance {0}", MessageHelper.InfoString(persister, id, source.Factory));
                }

                bool      regenerate = persister.IsIdentifierAssignedByInsert;            // prefer re-generation of identity!
                EntityKey key        = regenerate ? null : source.GenerateEntityKey(id, persister);

                await(PerformSaveOrReplicateAsync(entity, key, persister, regenerate, replicationMode, source, true, cancellationToken)).ConfigureAwait(false);
            }
        }
		private static bool IsVersionChanged(object entity, IEventSource source, IEntityPersister persister, object target)
		{
			if (!persister.IsVersioned)
			{
				return false;
			}
			// for merging of versioned entities, we consider the version having
			// been changed only when:
			// 1) the two version values are different;
			//      *AND*
			// 2) The target actually represents database state!
			//
			// This second condition is a special case which allows
			// an entity to be merged during the same transaction
			// (though during a seperate operation) in which it was
			// originally persisted/saved
			bool changed =
				!persister.VersionType.IsSame(persister.GetVersion(target, source.EntityMode),
				                              persister.GetVersion(entity, source.EntityMode), source.EntityMode);

			// TODO : perhaps we should additionally require that the incoming entity
			// version be equivalent to the defined unsaved-value?
			return changed && ExistsInDatabase(target, source, persister);
		}
Beispiel #15
0
        public override void Execute()
        {
            ISessionImplementor session = Session;
            object           id         = Id;
            IEntityPersister persister  = Persister;
            object           instance   = Instance;

            bool      statsEnabled = Session.Factory.Statistics.IsStatisticsEnabled;
            Stopwatch stopwatch    = null;

            if (statsEnabled)
            {
                stopwatch = Stopwatch.StartNew();
            }

            bool veto = PreUpdate();

            ISessionFactoryImplementor factory = Session.Factory;

            if (persister.IsVersionPropertyGenerated)
            {
                // we need to grab the version value from the entity, otherwise
                // we have issues with generated-version entities that may have
                // multiple actions queued during the same flush
                previousVersion = persister.GetVersion(instance);
            }

            CacheKey ck = null;

            if (persister.HasCache)
            {
                ck    = session.GenerateCacheKey(id, persister.IdentifierType, persister.RootEntityName);
                slock = persister.Cache.Lock(ck, previousVersion);
            }

            if (!veto)
            {
                persister.Update(id, state, dirtyFields, hasDirtyCollection, previousState, previousVersion, instance, null, session);
            }

            EntityEntry entry = Session.PersistenceContext.GetEntry(instance);

            if (entry == null)
            {
                throw new AssertionFailure("Possible nonthreadsafe access to session");
            }

            if (entry.Status == Status.Loaded || persister.IsVersionPropertyGenerated)
            {
                // get the updated snapshot of the entity state by cloning current state;
                // it is safe to copy in place, since by this time no-one else (should have)
                // has a reference  to the array
                TypeHelper.DeepCopy(state, persister.PropertyTypes, persister.PropertyCheckability, state, Session);
                if (persister.HasUpdateGeneratedProperties)
                {
                    // this entity defines property generation, so process those generated
                    // values...
                    persister.ProcessUpdateGeneratedProperties(id, instance, state, Session);
                    if (persister.IsVersionPropertyGenerated)
                    {
                        nextVersion = Versioning.GetVersion(state, persister);
                    }
                }
                // have the entity entry perform post-update processing, passing it the
                // update state and the new version (if one).
                entry.PostUpdate(instance, state, nextVersion);
            }

            if (persister.HasCache)
            {
                if (persister.IsCacheInvalidationRequired || entry.Status != Status.Loaded)
                {
                    persister.Cache.Evict(ck);
                }
                else
                {
                    CacheEntry ce = CacheEntry.Create(state, persister, nextVersion, Session, instance);
                    cacheEntry = persister.CacheEntryStructure.Structure(ce);

                    bool put = persister.Cache.Update(ck, cacheEntry, nextVersion, previousVersion);

                    if (put && factory.Statistics.IsStatisticsEnabled)
                    {
                        factory.StatisticsImplementor.SecondLevelCachePut(Persister.Cache.RegionName);
                    }
                }
            }

            PostUpdate();

            if (statsEnabled && !veto)
            {
                stopwatch.Stop();
                factory.StatisticsImplementor.UpdateEntity(Persister.EntityName, stopwatch.Elapsed);
            }
        }
		protected virtual void PerformUpdate(SaveOrUpdateEvent @event, object entity, IEntityPersister persister)
		{
			if (!persister.IsMutable)
			{
				log.Debug("immutable instance passed to PerformUpdate(), locking");
			}

			if (log.IsDebugEnabled)
			{
				log.Debug("updating " + MessageHelper.InfoString(persister, @event.RequestedId, @event.Session.Factory));
			}

			IEventSource source = @event.Session;

			EntityKey key = new EntityKey(@event.RequestedId, persister, source.EntityMode);

			source.PersistenceContext.CheckUniqueness(key, entity);

			if (InvokeUpdateLifecycle(entity, persister, source))
			{
				Reassociate(@event, @event.Entity, @event.RequestedId, persister);
				return;
			}

			// this is a transient object with existing persistent state not loaded by the session
			new OnUpdateVisitor(source, @event.RequestedId, entity).Process(entity, persister);

			//TODO: put this stuff back in to read snapshot from
			//      the second-level cache (needs some extra work)
			/*Object[] cachedState = null;
			
			if ( persister.hasCache() ) {
			CacheEntry entry = (CacheEntry) persister.getCache()
			.get( event.getRequestedId(), source.getTimestamp() );
			cachedState = entry==null ? 
			null : 
			entry.getState(); //TODO: half-assemble this stuff
			}*/

			source.PersistenceContext.AddEntity(
				entity, 
				persister.IsMutable ? Status.Loaded : Status.ReadOnly,
				null, 
				key,
				persister.GetVersion(entity, source.EntityMode), 
				LockMode.None, 
				true, 
				persister,
				false,
				true);

			//persister.AfterReassociate(entity, source); TODO H3.2 not ported

			if (log.IsDebugEnabled)
			{
				log.Debug("updating " + MessageHelper.InfoString(persister, @event.RequestedId, source.Factory));
			}

			CascadeOnUpdate(@event, persister, entity);
		}