public override void Process(object obj, IClassPersister persister) { object[] values = persister.GetPropertyValues(obj); IType[] types = persister.PropertyTypes; ProcessValues(values, types); if (IsSubstitutionRequired) { persister.SetPropertyValues(obj, values); } }
/// <summary> /// /// </summary> /// <param name="obj"></param> /// <param name="persister"></param> /// <param name="session"></param> /// <returns></returns> private static object[] Disassemble(object obj, IClassPersister persister, ISessionImplementor session) { object[] values = persister.GetPropertyValues(obj); IType[] propertyTypes = persister.PropertyTypes; for (int i = 0; i < values.Length; i++) { values[i] = propertyTypes[i].Disassemble(values[i], session); } return(values); }
/// <summary> /// /// </summary> /// <param name="obj"></param> /// <param name="persister"></param> /// <param name="session"></param> /// <returns></returns> private static object[ ] Disassemble( object obj, IClassPersister persister, ISessionImplementor session ) { object[ ] values = persister.GetPropertyValues( obj ); IType[ ] propertyTypes = persister.PropertyTypes; for( int i = 0; i < values.Length; i++ ) { values[ i ] = propertyTypes[ i ].Disassemble( values[ i ], session ); } return values; }
public override void Process(object obj, IClassPersister persister) { object[] values = persister.GetPropertyValues( obj ); IType[] types = persister.PropertyTypes; ProcessValues( values, types ); if( IsSubstitutionRequired ) { persister.SetPropertyValues( obj, values ); } }
/// <summary> /// Walk the tree starting from the given entity. /// </summary> /// <param name="obj"></param> /// <param name="persister"></param> public virtual void Process(object obj, IClassPersister persister) { ProcessValues( persister.GetPropertyValues(obj), persister.PropertyTypes); }
/// <summary> /// Walk the tree starting from the given entity. /// </summary> /// <param name="obj"></param> /// <param name="persister"></param> public virtual void Process(object obj, IClassPersister persister) { ProcessValues( persister.GetPropertyValues( obj ), persister.PropertyTypes ); }
private object DoSave( object theObj, Key key, IClassPersister persister, bool replicate, bool useIdentityColumn, Cascades.CascadingAction cascadeAction, object anything ) { if( persister.ImplementsValidatable ) { ( ( IValidatable ) theObj ).Validate(); } object id; if( useIdentityColumn ) { id = null; ExecuteInserts(); } else { id = key.Identifier; } // Put a placeholder in entries, so we don't recurse back to try and Save() the // same object again. QUESTION: Should this be done before OnSave() is called? // likewise, should it be done before OnUpdate()? AddEntry( theObj, Status.Saving, null, id, null, LockMode.Write, useIdentityColumn, persister, false ); // okay if id is null here // cascade-save to many-to-one BEFORE the parent is saved cascading++; try { Cascades.Cascade( this, persister, theObj, cascadeAction, CascadePoint.CascadeBeforeInsertAfterDelete, anything ); } finally { cascading--; } object[ ] values = persister.GetPropertyValues( theObj ); IType[ ] types = persister.PropertyTypes; bool substitute = false; if( !replicate ) { substitute = interceptor.OnSave( theObj, id, values, persister.PropertyNames, types ); // Keep the existing version number in the case of replicate! if( persister.IsVersioned ) { // IsUnsavedVersion bit below is NHibernate-specific substitute = Versioning.SeedVersion( values, persister.VersionProperty, persister.VersionType, persister.IsUnsavedVersion( values ) ) || substitute; } } if( persister.HasCollections ) { // TODO: make OnReplicateVisitor extend WrapVisitor if( replicate ) { OnReplicateVisitor visitor = new OnReplicateVisitor( this, id ); visitor.ProcessValues( values, types ); } WrapVisitor visitor2 = new WrapVisitor( this ); // substitutes into values by side-effect visitor2.ProcessValues( values, types ); substitute = substitute || visitor2.IsSubstitutionRequired; } if( substitute ) { persister.SetPropertyValues( theObj, values ); } TypeFactory.DeepCopy( values, types, persister.PropertyUpdateability, values ); NullifyTransientReferences( values, types, useIdentityColumn, theObj ); CheckNullability( values, persister, false ); if( useIdentityColumn ) { ScheduledIdentityInsertion insert = new ScheduledIdentityInsertion( values, theObj, persister, this ); Execute( insert ); id = insert.GeneratedId; persister.SetIdentifier( theObj, id ); key = new Key( id, persister ); CheckUniqueness( key, theObj ); } object version = Versioning.GetVersion( values, persister ); AddEntity( key, theObj ); AddEntry( theObj, Status.Loaded, values, id, version, LockMode.Write, useIdentityColumn, persister, replicate ); nonExists.Remove( key ); if( !useIdentityColumn ) { insertions.Add( new ScheduledInsertion( id, values, theObj, version, persister, this ) ); } // cascade-save to collections AFTER the collection owner was saved cascading++; try { Cascades.Cascade( this, persister, theObj, cascadeAction, CascadePoint.CascadeAfterInsertBeforeDelete, anything ); } finally { cascading--; } return id; }
private EntityEntry Reassociate( object obj, object id, IClassPersister persister ) { if( log.IsDebugEnabled ) { log.Debug( "reassociating transient instance: " + MessageHelper.InfoString( persister, id ) ); } Key key = new Key( id, persister ); CheckUniqueness( key, obj ); AddEntity( key, obj ); Object[ ] values = persister.GetPropertyValues( obj ); TypeFactory.DeepCopy( values, persister.PropertyTypes, persister.PropertyUpdateability, values ); object version = Versioning.GetVersion( values, persister ); EntityEntry newEntry = AddEntry( obj, Status.Loaded, values, id, version, LockMode.None, true, persister, false ); new OnLockVisitor( this, id ).Process( obj, persister ); return newEntry; }
private void DoDelete( object obj, EntityEntry entry, IClassPersister persister ) { if( log.IsDebugEnabled ) { log.Debug( "deleting " + MessageHelper.InfoString( persister, entry.Id ) ); } IType[ ] propTypes = persister.PropertyTypes; object version = entry.Version; object[ ] loadedState; if( entry.LoadedState == null ) { //ie the object came in from Update() loadedState = persister.GetPropertyValues( obj ); } else { loadedState = entry.LoadedState; } entry.DeletedState = new object[loadedState.Length]; TypeFactory.DeepCopy( loadedState, propTypes, persister.PropertyUpdateability, entry.DeletedState ); interceptor.OnDelete( obj, entry.Id, entry.DeletedState, persister.PropertyNames, propTypes ); entry.Status = Status.Deleted; // before cascade and Lifecycle callback, so we are circular-reference safe Key key = new Key( entry.Id, persister ); IList deletionsByOnDelete = null; ISet nullifiablesAfterOnDelete = null; // do Lifecycle callback before cascades, since this can veto if( persister.ImplementsLifecycle ) { ISet oldNullifiables = ( ISet ) nullifiables.Clone(); ArrayList oldDeletions = ( ArrayList ) deletions.Clone(); nullifiables.Add( key ); //the deletion of the parent is actually executed BEFORE any deletion from onDelete() try { log.Debug( "calling onDelete()" ); if( ( ( ILifecycle ) obj ).OnDelete( this ) == LifecycleVeto.Veto ) { //rollback deletion entry.Status = Status.Loaded; entry.DeletedState = null; nullifiables = oldNullifiables; log.Debug( "deletion vetoed by OnDelete()" ); return; // don't let it cascade } } catch( Exception ) { //rollback deletion entry.Status = Status.Loaded; entry.DeletedState = null; nullifiables = oldNullifiables; throw; } //note, the following assumes that onDelete() didn't cause the session to be flushed! // TODO: add a better check that it doesn't if( oldDeletions.Count > deletions.Count ) { throw new HibernateException( "session was flushed during onDelete()" ); } deletionsByOnDelete = Sublist( deletions, oldDeletions.Count, deletions.Count ); deletions = oldDeletions; nullifiablesAfterOnDelete = nullifiables; nullifiables = oldNullifiables; } cascading++; try { // cascade-delete to collections "BEFORE" the collection owner is deleted Cascades.Cascade( this, persister, obj, Cascades.CascadingAction.ActionDelete, CascadePoint.CascadeAfterInsertBeforeDelete, null ); } finally { cascading--; } NullifyTransientReferences( entry.DeletedState, propTypes, false, obj ); // NH: commented out, seems illogical to check for nulls here //CheckNullability( entry.DeletedState, persister, true ); nullifiables.Add( key ); ScheduledDeletion delete = new ScheduledDeletion( entry.Id, version, obj, persister, this ); deletions.Add( delete ); // Ensures that containing deletions happen before sub-deletions if( persister.ImplementsLifecycle ) { // after nullify, because we don't want to nullify references to subdeletions nullifiables.AddAll( nullifiablesAfterOnDelete ); // after deletions.add(), to respect foreign key constraints deletions.AddRange( deletionsByOnDelete ); } cascading++; try { // cascade-delete to many-to-one AFTER the parent was deleted Cascades.Cascade( this, persister, obj, Cascades.CascadingAction.ActionDelete, CascadePoint.CascadeBeforeInsertAfterDelete ); } finally { cascading--; } }