/// <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)); }
public virtual void OnReplicate(ReplicateEvent @event) { IEventSource source = @event.Session; if (source.PersistenceContext.ReassociateIfUninitializedProxy(@event.Entity)) { log.Debug("uninitialized proxy passed to replicate()"); return; } object entity = source.PersistenceContext.UnproxyAndReassociate(@event.Entity); 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, source.EntityMode); 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 = persister.GetCurrentVersion(id, source); } if (oldVersion != null) { if (log.IsDebugEnabled) { log.Debug("found existing row for " + MessageHelper.InfoString(persister, id, source.Factory)); } // HHH-2378 object realOldVersion = persister.IsVersioned ? oldVersion : null; bool canReplicate = replicationMode.ShouldOverwriteCurrentVersion(entity, realOldVersion, persister.GetVersion(entity, source.EntityMode), persister.VersionType); if (canReplicate) { //will result in a SQL UPDATE: PerformReplication(entity, id, realOldVersion, persister, replicationMode, source); } 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 " + MessageHelper.InfoString(persister, id, source.Factory)); } bool regenerate = persister.IsIdentifierAssignedByInsert; // prefer re-generation of identity! EntityKey key = regenerate ? null : new EntityKey(id, persister, source.EntityMode); PerformSaveOrReplicate(entity, key, persister, regenerate, replicationMode, source, true); } }