/// <summary> /// Possibly unproxy the given reference and reassociate it with the current session. /// </summary> /// <param name="maybeProxy">The reference to be unproxied if it currently represents a proxy. </param> /// <param name="cancellationToken">A cancellation token that can be used to cancel the work</param> /// <returns> The unproxied instance. </returns> public Task <object> UnproxyAndReassociateAsync(object maybeProxy, CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) { return(Task.FromCanceled <object>(cancellationToken)); } try { // TODO H3.2 Not ported //ElementWrapper wrapper = maybeProxy as ElementWrapper; //if (wrapper != null) //{ // maybeProxy = wrapper.Element; //} if (maybeProxy.IsProxy()) { var proxy = maybeProxy as INHibernateProxy; ILazyInitializer li = proxy.HibernateLazyInitializer; ReassociateProxy(li, proxy); return(li.GetImplementationAsync(cancellationToken)); //initialize + unwrap the object } return(Task.FromResult <object>(maybeProxy)); } catch (Exception ex) { return(Task.FromException <object>(ex)); } }
/// <summary> /// Given that there is a pre-existing proxy. /// Initialize it if necessary; narrow if necessary. /// </summary> private object ReturnNarrowedProxy(LoadEvent @event, IEntityPersister persister, EntityKey keyToLoad, LoadType options, IPersistenceContext persistenceContext, object proxy) { log.Debug("entity proxy found in session cache"); var castedProxy = (INHibernateProxy)proxy; ILazyInitializer li = castedProxy.HibernateLazyInitializer; if (li.Unwrap) { return(li.GetImplementation()); } object impl = null; if (!options.IsAllowProxyCreation) { impl = Load(@event, persister, keyToLoad, options); // NH Different behavior : NH-1252 if (impl == null && !options.IsAllowNulls) { @event.Session.Factory.EntityNotFoundDelegate.HandleEntityNotFound(persister.EntityName, keyToLoad.Identifier); } } if (impl == null && !options.IsAllowProxyCreation && options.ExactPersister) { // NH Different behavior : NH-1252 return(null); } return(persistenceContext.NarrowProxy(castedProxy, persister, keyToLoad, impl)); }
public virtual bool Contains(object collection, object childObject, ISessionImplementor session) { // we do not have to worry about queued additions to uninitialized // collections, since they can only occur for inverse collections! IEnumerable elems = GetElementsIterator(collection, session); foreach (object elem in elems) { object element = elem; // worrying about proxies is perhaps a little bit of overkill here... if (element.IsProxy()) { INHibernateProxy proxy = element as INHibernateProxy; ILazyInitializer li = proxy.HibernateLazyInitializer; if (!li.IsUninitialized) { element = li.GetImplementation(); } } if (element == childObject) { return(true); } } return(false); }
/// <summary> /// Given that there is a pre-existing proxy. /// Initialize it if necessary; narrow if necessary. /// </summary> private async Task <object> ReturnNarrowedProxyAsync(LoadEvent @event, IEntityPersister persister, EntityKey keyToLoad, LoadType options, IPersistenceContext persistenceContext, object proxy, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); log.Debug("entity proxy found in session cache"); var castedProxy = (INHibernateProxy)proxy; ILazyInitializer li = castedProxy.HibernateLazyInitializer; if (li.Unwrap) { return(await(li.GetImplementationAsync(cancellationToken)).ConfigureAwait(false)); } object impl = null; if (!options.IsAllowProxyCreation) { impl = await(LoadAsync(@event, persister, keyToLoad, options, cancellationToken)).ConfigureAwait(false); // NH Different behavior : NH-1252 if (impl == null && !options.IsAllowNulls) { @event.Session.Factory.EntityNotFoundDelegate.HandleEntityNotFound(persister.EntityName, keyToLoad.Identifier); } } if (impl == null && !options.IsAllowProxyCreation && options.ExactPersister) { // NH Different behavior : NH-1252 return(null); } return(persistenceContext.NarrowProxy(castedProxy, persister, keyToLoad, impl)); }
/// <summary> /// Check if the property is initialized. If the named property does not exist /// or is not persistent, this method always returns <tt>true</tt>. /// </summary> /// <param name="proxy">The potential proxy </param> /// <param name="propertyName">the name of a persistent attribute of the object </param> /// <returns> /// true if the named property of the object is not listed as uninitialized; /// false if the object is an uninitialized proxy, or the named property is uninitialized /// </returns> public static bool IsPropertyInitialized(object proxy, string propertyName) { object entity; if (proxy.IsProxy()) { ILazyInitializer li = ((INHibernateProxy)proxy).HibernateLazyInitializer; if (li.IsUninitialized) { return(false); } else { entity = li.GetImplementation(); } } else { entity = proxy; } if (entity is IFieldInterceptorAccessor interceptorAccessor) { var interceptor = interceptorAccessor.FieldInterceptor; return(interceptor == null || interceptor.IsInitializedField(propertyName)); } else { return(true); } }
/// <summary> /// Get the true, underlying class of a proxied persistent class. This operation /// will NOT initialize the proxy and thus may return an incorrect result. /// </summary> /// <param name="entity">a persistable object or proxy</param> /// <returns>guessed class of the instance</returns> /// <remarks> /// This method is approximate match for Session.bestGuessEntityName in H3.2 /// </remarks> public static System.Type GuessClass(object entity) { var proxy = entity as INHibernateProxy; //todo 修改源码 if (entity.IsProxy() && proxy != null) { ILazyInitializer li = proxy.HibernateLazyInitializer; if (li.IsUninitialized || li.GetImplementation().GetType().Name.Contains("Proxy")) { return(li.PersistentClass); } return(li.GetImplementation().GetType()); } var propInfo = entity.GetType().GetProperty("EntityType"); if (propInfo != null) { var entityType = propInfo.GetValue(entity, null) as System.Type; if (entityType != null) { return(entityType); } } var fieldInterceptorAccessor = entity as IFieldInterceptorAccessor; if (fieldInterceptorAccessor != null) { var fieldInterceptor = fieldInterceptorAccessor.FieldInterceptor; return(fieldInterceptor.MappedClass); } return(entity.GetType()); }
/// <summary> /// Check if the property is initialized. If the named property does not exist /// or is not persistent, this method always returns <tt>true</tt>. /// </summary> /// <param name="proxy">The potential proxy </param> /// <param name="propertyName">the name of a persistent attribute of the object </param> /// <returns> /// true if the named property of the object is not listed as uninitialized; /// false if the object is an uninitialized proxy, or the named property is uninitialized /// </returns> public static bool IsPropertyInitialized(object proxy, string propertyName) { object entity; if (proxy is INHibernateProxy) { ILazyInitializer li = ((INHibernateProxy)proxy).HibernateLazyInitializer; if (li.IsUninitialized) { return(false); } else { entity = li.GetImplementation(); } } else { entity = proxy; } if (FieldInterceptionHelper.IsInstrumented(entity)) { IFieldInterceptor interceptor = FieldInterceptionHelper.ExtractFieldInterceptor(entity); return(interceptor == null || interceptor.IsInitializedField(propertyName)); } else { return(true); } }
/// <summary> /// Determine if the object already exists in the database, using a "best guess" /// </summary> private async Task <bool> IsNullifiableAsync(string entityName, object obj, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); //if (obj == org.hibernate.intercept.LazyPropertyInitializer_Fields.UNFETCHED_PROPERTY) // return false; //this is kinda the best we can do... if (obj.IsProxy()) { INHibernateProxy proxy = obj as INHibernateProxy; // if its an uninitialized proxy it can't be transient ILazyInitializer li = proxy.HibernateLazyInitializer; if (li.GetImplementation(session) == null) { return(false); // ie. we never have to null out a reference to // an uninitialized proxy } else { //unwrap it obj = await(li.GetImplementationAsync(cancellationToken)).ConfigureAwait(false); } } // if it was a reference to self, don't need to nullify // unless we are using native id generation, in which // case we definitely need to nullify if (obj == self) { // TODO H3.2: Different behaviour //return isEarlyInsert || (isDelete && session.Factory.Dialect.HasSelfReferentialForeignKeyBug); return(isEarlyInsert || isDelete); } // See if the entity is already bound to this session, if not look at the // entity identifier and assume that the entity is persistent if the // id is not "unsaved" (that is, we rely on foreign keys to keep // database integrity) EntityEntry entityEntry = session.PersistenceContext.GetEntry(obj); if (entityEntry == null) { return(await(IsTransientSlowAsync(entityName, obj, session, cancellationToken)).ConfigureAwait(false)); } else { return(entityEntry.IsNullifiable(isEarlyInsert, session)); } }
/// <summary> /// Get the identifier value of an instance or proxy. /// <p/> /// Intended only for loggin purposes!!! /// </summary> /// <param name="obj">The object from which to extract the identifier.</param> /// <param name="persister">The entity persister </param> /// <returns> The extracted identifier. </returns> private static object GetIdentifier(object obj, IEntityPersister persister) { if (obj.IsProxy()) { INHibernateProxy proxy = obj as INHibernateProxy; ILazyInitializer li = proxy.HibernateLazyInitializer; return(li.Identifier); } else { return(persister.GetIdentifier(obj)); } }
/// <summary> /// Get the identifier value of an instance or proxy. /// <p/> /// Intended only for loggin purposes!!! /// </summary> /// <param name="obj">The object from which to extract the identifier.</param> /// <param name="persister">The entity persister </param> /// <param name="entityMode">The entity mode </param> /// <returns> The extracted identifier. </returns> private static object GetIdentifier(object obj, IEntityPersister persister, EntityMode entityMode) { INHibernateProxy proxy = obj as INHibernateProxy; if (proxy != null) { ILazyInitializer li = proxy.HibernateLazyInitializer; return(li.Identifier); } else { return(persister.GetIdentifier(obj, entityMode)); } }
public virtual async Task OnPersistAsync(PersistEvent @event, IDictionary createdAlready, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); ISessionImplementor source = @event.Session; object obj = @event.Entity; object entity; if (obj.IsProxy()) { ILazyInitializer li = ((INHibernateProxy)obj).HibernateLazyInitializer; if (li.IsUninitialized) { if (li.Session == source) { return; //NOTE EARLY EXIT! } else { throw new PersistentObjectException("uninitialized proxy passed to persist()"); } } entity = await(li.GetImplementationAsync(cancellationToken)).ConfigureAwait(false); } else { entity = obj; } EntityState entityState = await(GetEntityStateAsync(entity, @event.EntityName, source.PersistenceContext.GetEntry(entity), source, cancellationToken)).ConfigureAwait(false); switch (entityState) { case EntityState.Persistent: await(EntityIsPersistentAsync(@event, createdAlready, cancellationToken)).ConfigureAwait(false); break; case EntityState.Transient: await(EntityIsTransientAsync(@event, createdAlready, cancellationToken)).ConfigureAwait(false); break; case EntityState.Detached: throw new PersistentObjectException("detached entity passed to persist: " + GetLoggableName(@event.EntityName, entity)); default: throw new ObjectDeletedException("deleted instance passed to merge", null, GetLoggableName(@event.EntityName, entity)); } }
public virtual void OnPersist(PersistEvent @event, IDictionary createdAlready) { ISessionImplementor source = @event.Session; object obj = @event.Entity; object entity; if (obj is INHibernateProxy) { ILazyInitializer li = ((INHibernateProxy)obj).HibernateLazyInitializer; if (li.IsUninitialized) { if (li.Session == source) { return; //NOTE EARLY EXIT! } else { throw new PersistentObjectException("uninitialized proxy passed to persist()"); } } entity = li.GetImplementation(); } else { entity = obj; } EntityState entityState = GetEntityState(entity, @event.EntityName, source.PersistenceContext.GetEntry(entity), source); switch (entityState) { case EntityState.Persistent: EntityIsPersistent(@event, createdAlready); break; case EntityState.Transient: EntityIsTransient(@event, createdAlready); break; case EntityState.Detached: throw new PersistentObjectException("detached entity passed to persist: " + GetLoggableName(@event.EntityName, entity)); default: throw new ObjectDeletedException("deleted instance passed to merge", null, GetLoggableName(@event.EntityName, entity)); } }
/// <summary> /// Get the true, underlying class of a proxied persistent class. This operation /// will NOT initialize the proxy and thus may return an incorrect result. /// </summary> /// <param name="entity">a persistable object or proxy</param> /// <returns>guessed class of the instance</returns> /// <remarks> /// This method is approximate match for Session.bestGuessEntityName in H3.2 /// </remarks> public static System.Type GuessClass(object entity) { if (entity.IsProxy()) { var proxy = entity as INHibernateProxy; ILazyInitializer li = proxy.HibernateLazyInitializer; if (li.IsUninitialized) { return(li.PersistentClass); } return(li.GetImplementation().GetType()); } var fieldInterceptorAccessor = entity as IFieldInterceptorAccessor; if (fieldInterceptorAccessor != null) { var fieldInterceptor = fieldInterceptorAccessor.FieldInterceptor; return(fieldInterceptor.MappedClass); } return(entity.GetType()); }
public TEspecializado InicializarLazyLoad <TEspecializado>(object paraInicializar) { if (null == paraInicializar) { throw new ArgumentNullException("paraInicializar"); } if (typeof(TEspecializado) == paraInicializar.GetType()) { return((TEspecializado)paraInicializar); } if (false == typeof(INHibernateProxy).IsAssignableFrom(paraInicializar.GetType())) { throw new Exception(string.Format("{0} nao implementa INHibernateProxy", paraInicializar.GetType().FullName)); } ILazyInitializer lazyInitializer = ((INHibernateProxy)paraInicializar).HibernateLazyInitializer; return((TEspecializado)lazyInitializer.GetImplementation()); }
/// <summary> /// Get the true, underlying class of a proxied persistent class. This operation /// will NOT initialize the proxy and thus may return an incorrect result. /// </summary> /// <param name="entity">a persistable object or proxy</param> /// <returns>guessed class of the instance</returns> /// <remarks> /// This method is approximate match for Session.bestGuessEntityName in H3.2 /// </remarks> public static System.Type GuessClass(object entity) { INHibernateProxy proxy = entity as INHibernateProxy; if (proxy != null) { ILazyInitializer li = proxy.HibernateLazyInitializer; if (li.IsUninitialized) { return(li.PersistentClass); } else { return(li.GetImplementation().GetType()); } } else { return(entity.GetType()); } }
public virtual async Task OnEvictAsync(EvictEvent @event, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); IEventSource source = @event.Session; object obj = @event.Entity; IPersistenceContext persistenceContext = source.PersistenceContext; if (obj.IsProxy()) { ILazyInitializer li = ((INHibernateProxy)obj).HibernateLazyInitializer; object id = li.Identifier; IEntityPersister persister = source.Factory.GetEntityPersister(li.EntityName); if (id == null) { throw new ArgumentException("null identifier"); } EntityKey key = source.GenerateEntityKey(id, persister); persistenceContext.RemoveProxy(key); if (!li.IsUninitialized) { object entity = persistenceContext.RemoveEntity(key); if (entity != null) { EntityEntry e = @event.Session.PersistenceContext.RemoveEntry(entity); await(DoEvictAsync(entity, key, e.Persister, @event.Session, cancellationToken)).ConfigureAwait(false); } } li.UnsetSession(); } else { EntityEntry e = persistenceContext.RemoveEntry(obj); if (e != null) { persistenceContext.RemoveEntity(e.EntityKey); await(DoEvictAsync(obj, e.EntityKey, e.Persister, source, cancellationToken)).ConfigureAwait(false); } } }
public virtual void OnEvict(EvictEvent @event) { IEventSource source = @event.Session; object obj = @event.Entity; IPersistenceContext persistenceContext = source.PersistenceContext; if (obj is INHibernateProxy) { ILazyInitializer li = ((INHibernateProxy)obj).HibernateLazyInitializer; object id = li.Identifier; IEntityPersister persister = source.Factory.GetEntityPersister(li.EntityName); if (id == null) { throw new ArgumentException("null identifier"); } EntityKey key = new EntityKey(id, persister, source.EntityMode); persistenceContext.RemoveProxy(key); if (!li.IsUninitialized) { object entity = persistenceContext.RemoveEntity(key); if (entity != null) { EntityEntry e = @event.Session.PersistenceContext.RemoveEntry(entity); DoEvict(entity, key, e.Persister, @event.Session); } } li.Session = null; } else { EntityEntry e = persistenceContext.RemoveEntry(obj); if (e != null) { EntityKey key = new EntityKey(e.Id, e.Persister, source.EntityMode); persistenceContext.RemoveEntity(key); DoEvict(obj, key, e.Persister, source); } } }
public static bool IsPropertyInitialized(object proxy, string propertyName) { object entity; if (!IsProxyFactoryConfigurated()) { //if the proxy provider it's not configurated, can't be a proxy neither an instrumented field. return(true); } if (proxy.IsProxy()) { ILazyInitializer li = ((INHibernateProxy)proxy).HibernateLazyInitializer; if (li.IsUninitialized) { return(false); } else { entity = li.GetImplementation(); } } else { entity = proxy; } if (FieldInterceptionHelper.IsInstrumented(entity)) { IFieldInterceptor interceptor = FieldInterceptionHelper.ExtractFieldInterceptor(entity); return(interceptor == null || interceptor.IsInitializedField(propertyName)); } else { return(true); } }
/// <summary> /// Associate a proxy that was instantiated by another session with this session /// </summary> /// <param name="li">The proxy initializer. </param> /// <param name="proxy">The proxy to reassociate. </param> private void ReassociateProxy(ILazyInitializer li, INHibernateProxy proxy) { if (li.Session != Session) { IEntityPersister persister = session.Factory.GetEntityPersister(li.EntityName); EntityKey key = new EntityKey(li.Identifier, persister, session.EntityMode); // any earlier proxy takes precedence if (!proxiesByKey.ContainsKey(key)) { proxiesByKey[key] = proxy; } proxy.HibernateLazyInitializer.Session = Session; } }
public virtual void OnMerge(MergeEvent @event, IDictionary copyCache) { IEventSource source = @event.Session; object original = @event.Original; if (original != null) { object entity; if (original is INHibernateProxy) { ILazyInitializer li = ((INHibernateProxy)original).HibernateLazyInitializer; if (li.IsUninitialized) { log.Debug("ignoring uninitialized proxy"); @event.Result = source.Load(li.PersistentClass, li.Identifier); return; //EARLY EXIT! } else { entity = li.GetImplementation(); } } else { entity = original; } if (copyCache.Contains(entity)) { log.Debug("already merged"); @event.Result = entity; } else { @event.Entity = entity; EntityState entityState = EntityState.Undefined; // Check the persistence context for an entry relating to this // entity to be merged... EntityEntry entry = source.PersistenceContext.GetEntry(entity); if (entry == null) { IEntityPersister persister = source.GetEntityPersister(@event.EntityName, entity); object id = persister.GetIdentifier(entity, source.EntityMode); if (id != null) { EntityKey key = new EntityKey(id, persister, source.EntityMode); object managedEntity = source.PersistenceContext.GetEntity(key); entry = source.PersistenceContext.GetEntry(managedEntity); if (entry != null) { // we have specialized case of a detached entity from the // perspective of the merge operation. Specifically, we // have an incoming entity instance which has a corresponding // entry in the current persistence context, but registered // under a different entity instance entityState = EntityState.Detached; } } } if (entityState == EntityState.Undefined) { entityState = GetEntityState(entity, @event.EntityName, entry, source); } switch (entityState) { case EntityState.Persistent: EntityIsPersistent(@event, copyCache); break; case EntityState.Transient: EntityIsTransient(@event, copyCache); break; case EntityState.Detached: EntityIsDetached(@event, copyCache); break; default: throw new ObjectDeletedException("deleted instance passed to merge", null, GetLoggableName(@event.EntityName, entity)); } } } }
public virtual async Task OnMergeAsync(MergeEvent @event, IDictionary copiedAlready, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); EventCache copyCache = (EventCache)copiedAlready; IEventSource source = @event.Session; object original = @event.Original; if (original != null) { object entity; if (original.IsProxy()) { ILazyInitializer li = ((INHibernateProxy)original).HibernateLazyInitializer; if (li.IsUninitialized) { log.Debug("ignoring uninitialized proxy"); @event.Result = await(source.LoadAsync(li.EntityName, li.Identifier, cancellationToken)).ConfigureAwait(false); return; //EARLY EXIT! } else { entity = await(li.GetImplementationAsync(cancellationToken)).ConfigureAwait(false); } } else { entity = original; } if (copyCache.Contains(entity) && copyCache.IsOperatedOn(entity)) { log.Debug("already in merge process"); @event.Result = entity; } else { if (copyCache.Contains(entity)) { log.Info("already in copyCache; setting in merge process"); copyCache.SetOperatedOn(entity, true); } @event.Entity = entity; EntityState entityState = EntityState.Undefined; if (ReferenceEquals(null, @event.EntityName)) { @event.EntityName = source.BestGuessEntityName(entity); } // Check the persistence context for an entry relating to this // entity to be merged... EntityEntry entry = source.PersistenceContext.GetEntry(entity); if (entry == null) { IEntityPersister persister = source.GetEntityPersister(@event.EntityName, entity); object id = persister.GetIdentifier(entity); if (id != null) { EntityKey key = source.GenerateEntityKey(id, persister); object managedEntity = source.PersistenceContext.GetEntity(key); entry = source.PersistenceContext.GetEntry(managedEntity); if (entry != null) { // we have specialized case of a detached entity from the // perspective of the merge operation. Specifically, we // have an incoming entity instance which has a corresponding // entry in the current persistence context, but registered // under a different entity instance entityState = EntityState.Detached; } } } if (entityState == EntityState.Undefined) { entityState = await(GetEntityStateAsync(entity, @event.EntityName, entry, source, cancellationToken)).ConfigureAwait(false); } switch (entityState) { case EntityState.Persistent: await(EntityIsPersistentAsync(@event, copyCache, cancellationToken)).ConfigureAwait(false); break; case EntityState.Transient: await(EntityIsTransientAsync(@event, copyCache, cancellationToken)).ConfigureAwait(false); break; case EntityState.Detached: await(EntityIsDetachedAsync(@event, copyCache, cancellationToken)).ConfigureAwait(false); break; default: throw new ObjectDeletedException("deleted instance passed to merge", null, GetLoggableName(@event.EntityName, entity)); } } } }