⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 defaultloadeventlistener.cs

📁 NHibernate NET开发者所需的
💻 CS
📖 第 1 页 / 共 2 页
字号:
			else
			{
				ck = null;
			}

			object entity;
			try
			{
				entity = Load(@event, persister, keyToLoad, options);
			}
			finally
			{
				if (persister.HasCache)
				{
					persister.Cache.Release(ck, sLock);
				}
			}

			object proxy = @event.Session.PersistenceContext.ProxyFor(persister, keyToLoad, entity);

			return proxy;
		}
		/// <summary> 
		/// Coordinates the efforts to load a given entity.  First, an attempt is
		/// made to load the entity from the session-level cache.  If not found there,
		/// an attempt is made to locate it in second-level cache.  Lastly, an
		/// attempt is made to load it directly from the datasource. 
		/// </summary>
		/// <param name="event">The load event </param>
		/// <param name="persister">The persister for the entity being requested for load </param>
		/// <param name="keyToLoad">The EntityKey representing the entity to be loaded. </param>
		/// <param name="options">The load options. </param>
		/// <returns> The loaded entity, or null. </returns>
		protected virtual object DoLoad(LoadEvent @event, IEntityPersister persister, EntityKey keyToLoad, LoadType options)
		{
			if (log.IsDebugEnabled)
			{
				log.Debug("attempting to resolve: " + MessageHelper.InfoString(persister, @event.EntityId, @event.Session.Factory));
			}

			object entity = LoadFromSessionCache(@event, keyToLoad, options);
			if (entity == RemovedEntityMarker)
			{
				log.Debug("load request found matching entity in context, but it is scheduled for removal; returning null");
				return null;
			}
			if (entity == InconsistentRTNClassMarker)
			{
				log.Debug("load request found matching entity in context, but the matched entity was of an inconsistent return type; returning null");
				return null;
			}
			if (entity != null)
			{
				if (log.IsDebugEnabled)
				{
					log.Debug("resolved object in session cache: " + MessageHelper.InfoString(persister, @event.EntityId, @event.Session.Factory));
				}
				return entity;
			}

			entity = LoadFromSecondLevelCache(@event, persister, options);
			if (entity != null)
			{
				if (log.IsDebugEnabled)
				{
					log.Debug("resolved object in second-level cache: " + MessageHelper.InfoString(persister, @event.EntityId, @event.Session.Factory));
				}
				return entity;
			}

			if (log.IsDebugEnabled)
			{
				log.Debug("object not resolved in any cache: " + MessageHelper.InfoString(persister, @event.EntityId, @event.Session.Factory));
			}

			return LoadFromDatasource(@event, persister, keyToLoad, options);
		}

		/// <summary> 
		/// Performs the process of loading an entity from the configured underlying datasource. 
		/// </summary>
		/// <param name="event">The load event </param>
		/// <param name="persister">The persister for the entity being requested for load </param>
		/// <param name="keyToLoad">The EntityKey representing the entity to be loaded. </param>
		/// <param name="options">The load options. </param>
		/// <returns> The object loaded from the datasource, or null if not found. </returns>
		protected virtual object LoadFromDatasource(LoadEvent @event, IEntityPersister persister, EntityKey keyToLoad, LoadType options)
		{
			ISessionImplementor source = @event.Session;
			object entity = persister.Load(@event.EntityId, @event.InstanceToLoad, @event.LockMode, source);

			if (@event.IsAssociationFetch && source.Factory.Statistics.IsStatisticsEnabled)
			{
				source.Factory.StatisticsImplementor.FetchEntity(@event.EntityClassName);
			}

			return entity;
		}

		/// <summary> 
		/// Attempts to locate the entity in the session-level cache. 
		/// </summary>
		/// <param name="event">The load event </param>
		/// <param name="keyToLoad">The EntityKey representing the entity to be loaded. </param>
		/// <param name="options">The load options. </param>
		/// <returns> The entity from the session-level cache, or null. </returns>
		/// <remarks>
		/// If allowed to return nulls, then if the entity happens to be found in
		/// the session cache, we check the entity type for proper handling
		/// of entity hierarchies.
		/// If checkDeleted was set to true, then if the entity is found in the
		/// session-level cache, it's current status within the session cache
		/// is checked to see if it has previously been scheduled for deletion.
		/// </remarks>
		protected virtual object LoadFromSessionCache(LoadEvent @event, EntityKey keyToLoad, LoadType options)
		{
			ISessionImplementor session = @event.Session;
			object old = session.GetEntityUsingInterceptor(keyToLoad);

			if (old != null)
			{
				// this object was already loaded
				EntityEntry oldEntry = session.PersistenceContext.GetEntry(old);
				if (options.IsCheckDeleted)
				{
					Status status = oldEntry.Status;
					if (status == Status.Deleted || status == Status.Gone)
					{
						return RemovedEntityMarker;
					}
				}
				if (options.IsAllowNulls)
				{
					IEntityPersister persister = @event.Session.Factory.GetEntityPersister(@event.EntityClassName);
					if (!persister.IsInstance(old, @event.Session.EntityMode))
					{
						return InconsistentRTNClassMarker;
					}
				}
				UpgradeLock(old, oldEntry, @event.LockMode, session);
			}
			return old;
		}


		/// <summary> Attempts to load the entity from the second-level cache. </summary>
		/// <param name="event">The load event </param>
		/// <param name="persister">The persister for the entity being requested for load </param>
		/// <param name="options">The load options. </param>
		/// <returns> The entity from the second-level cache, or null. </returns>
		protected virtual object LoadFromSecondLevelCache(LoadEvent @event, IEntityPersister persister, LoadType options)
		{
			ISessionImplementor source = @event.Session;
			bool useCache = persister.HasCache && ((source.CacheMode & CacheMode.Get) == CacheMode.Get)
				&& @event.LockMode.LessThan(LockMode.Read);

			if (useCache)
			{
				ISessionFactoryImplementor factory = source.Factory;

				CacheKey ck = new CacheKey(@event.EntityId, persister.IdentifierType, persister.RootEntityName, source.EntityMode, factory);
				object ce = persister.Cache.Get(ck, source.Timestamp);

				if (factory.Statistics.IsStatisticsEnabled)
				{
					if (ce == null)
						factory.StatisticsImplementor.SecondLevelCacheMiss(persister.Cache.RegionName);
					else
						factory.StatisticsImplementor.SecondLevelCacheHit(persister.Cache.RegionName);
				}

				if (ce != null)
				{
					CacheEntry entry = (CacheEntry)persister.CacheEntryStructure.Destructure(ce, factory);

					// Entity was found in second-level cache...
					// NH: Different behavior (take a look to options.ExactPersister (NH-295))
					if (!options.ExactPersister || persister.EntityMetamodel.SubclassEntityNames.Contains(entry.Subclass))
					{
						return AssembleCacheEntry(entry, @event.EntityId, persister, @event);
					}
				}
			}

			return null;
		}

		private object AssembleCacheEntry(CacheEntry entry, object id, IEntityPersister persister, LoadEvent @event)
		{
			object optionalObject = @event.InstanceToLoad;
			IEventSource session = @event.Session;
			ISessionFactoryImplementor factory = session.Factory;

			if (log.IsDebugEnabled)
			{
				log.Debug("assembling entity from second-level cache: " + MessageHelper.InfoString(persister, id, factory));
			}

			IEntityPersister subclassPersister = factory.GetEntityPersister(entry.Subclass);
			object result = optionalObject ?? session.Instantiate(subclassPersister, id);

			// make it circular-reference safe
			TwoPhaseLoad.AddUninitializedCachedEntity(new EntityKey(id, subclassPersister, session.EntityMode), result, subclassPersister, LockMode.None, entry.AreLazyPropertiesUnfetched, entry.Version, session);

			IType[] types = subclassPersister.PropertyTypes;
			object[] values = entry.Assemble(result, id, subclassPersister, session.Interceptor, session); // intializes result by side-effect
			TypeFactory.DeepCopy(values, types, subclassPersister.PropertyUpdateability, values, session);

			object version = Versioning.GetVersion(values, subclassPersister);
			if (log.IsDebugEnabled)
			{
				log.Debug("Cached Version: " + version);
			}

			IPersistenceContext persistenceContext = session.PersistenceContext;
			
			persistenceContext.AddEntry(result, Status.Loaded, values, id, version, LockMode.None, true, subclassPersister, false, entry.AreLazyPropertiesUnfetched);
			// TODO H3.2 subclassPersister.AfterInitialize(result, entry.AreLazyPropertiesUnfetched, session);

			persistenceContext.InitializeNonLazyCollections();
			// upgrade the lock if necessary:
			//lock(result, lockMode);

			//PostLoad is needed for EJB3
			//TODO: reuse the PostLoadEvent...
			PostLoadEvent postLoadEvent = new PostLoadEvent(session);
			postLoadEvent.Entity = result;
			postLoadEvent.Id = id;
			postLoadEvent.Persister = persister;

			IPostLoadEventListener[] listeners = session.Listeners.PostLoadEventListeners;
			for (int i = 0; i < listeners.Length; i++)
			{
				listeners[i].OnPostLoad(postLoadEvent);
			}
			return result;
		}
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -