예제 #1
0
        public override bool Equals(object obj)
        {
            CollectionKey that = (CollectionKey)obj;

            return(Equals(key, that.key) &&
                   Equals(role, that.role));
        }
		/// <summary> 
		/// Retrieve the collection that is being loaded as part of processing this result set. 
		/// </summary>
		/// <param name="persister">The persister for the collection being requested. </param>
		/// <param name="key">The key of the collection being requested. </param>
		/// <returns> The loading collection (see discussion above). </returns>
		/// <remarks>
		/// Basically, there are two valid return values from this method:<ul>
		/// <li>an instance of {@link PersistentCollection} which indicates to
		/// continue loading the result set row data into that returned collection
		/// instance; this may be either an instance already associated and in the
		/// midst of being loaded, or a newly instantiated instance as a matching
		/// associated collection was not found.</li>
		/// <li><i>null</i> indicates to ignore the corresponding result set row
		/// data relating to the requested collection; this indicates that either
		/// the collection was found to already be associated with the persistence
		/// context in a fully loaded state, or it was found in a loading state
		/// associated with another result set processing context.</li>
		/// </ul>
		/// </remarks>
		public IPersistentCollection GetLoadingCollection(ICollectionPersister persister, object key)
		{
			EntityMode em = loadContexts.PersistenceContext.Session.EntityMode;

			CollectionKey collectionKey = new CollectionKey(persister, key, em);
			if (log.IsDebugEnabled)
			{
				log.Debug("starting attempt to find loading collection [" + MessageHelper.InfoString(persister.Role, key) + "]");
			}
			LoadingCollectionEntry loadingCollectionEntry = loadContexts.LocateLoadingCollectionEntry(collectionKey);
			if (loadingCollectionEntry == null)
			{
				// look for existing collection as part of the persistence context
				IPersistentCollection collection = loadContexts.PersistenceContext.GetCollection(collectionKey);
				if (collection != null)
				{
					if (collection.WasInitialized)
					{
						log.Debug("collection already initialized; ignoring");
						return null; // ignore this row of results! Note the early exit
					}
					else
					{
						// initialize this collection
						log.Debug("collection not yet initialized; initializing");
					}
				}
				else
				{
					object owner = loadContexts.PersistenceContext.GetCollectionOwner(key, persister);
					bool newlySavedEntity = owner != null && loadContexts.PersistenceContext.GetEntry(owner).Status != Status.Loading && em != EntityMode.Xml;
					if (newlySavedEntity)
					{
						// important, to account for newly saved entities in query
						// todo : some kind of check for new status...
						log.Debug("owning entity already loaded; ignoring");
						return null;
					}
					else
					{
						// create one
						if (log.IsDebugEnabled)
						{
							log.Debug("instantiating new collection [key=" + key + ", rs=" + resultSet + "]");
						}
						collection = persister.CollectionType.Instantiate(loadContexts.PersistenceContext.Session, persister, key);
					}
				}
				collection.BeforeInitialize(persister, -1);
				collection.BeginRead();
				localLoadingCollectionKeys.Add(collectionKey);
				loadContexts.RegisterLoadingCollectionXRef(collectionKey, new LoadingCollectionEntry(resultSet, persister, key, collection));
				return collection;
			}
			else
			{
				if (loadingCollectionEntry.ResultSet == resultSet)
				{
					log.Debug("found loading collection bound to current result set processing; reading row");
					return loadingCollectionEntry.Collection;
				}
				else
				{
					// ignore this row, the collection is in process of
					// being loaded somewhere further "up" the stack
					log.Debug("collection is already being initialized; ignoring row");
					return null;
				}
			}
		}
예제 #3
0
		/// <summary> 
		/// Locate the LoadingCollectionEntry within *any* of the tracked
		/// <see cref="CollectionLoadContext"/>s.
		/// </summary>
		/// <param name="key">The collection key. </param>
		/// <returns> The located entry; or null. </returns>
		/// <remarks>
		/// Implementation note: package protected, as this is meant solely for use
		/// by <see cref="CollectionLoadContext"/> to be able to locate collections
		/// being loaded by other <see cref="CollectionLoadContext"/>s/ResultSets. 
		/// </remarks>
		internal LoadingCollectionEntry LocateLoadingCollectionEntry(CollectionKey key)
		{
			if (xrefLoadingCollectionEntries == null)
			{
				return null;
			}
			if (log.IsDebugEnabled)
			{
				log.Debug("attempting to locate loading collection entry [" + key + "] in any result-set context");
			}
			LoadingCollectionEntry rtn;
			xrefLoadingCollectionEntries.TryGetValue(key, out rtn);
			if (log.IsDebugEnabled)
			{
				log.Debug(string.Format("collection [{0}] {1} in load context", key, (rtn == null ? "located" : "not located")));
			}
			return rtn;
		}
예제 #4
0
		/// <summary> 
		/// The inverse of {@link #registerLoadingCollectionXRef}.  Here, we are done
		/// processing the said collection entry, so we remove it from the
		/// load context.
		/// </summary>
		/// <param name="key">The key of the collection we are done processing. </param>
		/// <remarks>
		/// The idea here is that other loading collections can now reference said
		/// collection directly from the {@link PersistenceContext} because it
		/// has completed its load cycle.
		/// Implementation note: package protected, as this is meant solely for use
		/// by {@link CollectionLoadContext} to be able to locate collections
		/// being loaded by other {@link CollectionLoadContext}s/{@link ResultSet}s.
		/// </remarks>
		internal void UnregisterLoadingCollectionXRef(CollectionKey key)
		{
			if (!HasRegisteredLoadingCollectionEntries)
			{
				return;
			}
			xrefLoadingCollectionEntries.Remove(key);
		}
예제 #5
0
		/// <summary> 
		/// Register a loading collection xref. 
		/// </summary>
		/// <param name="entryKey">The xref collection key </param>
		/// <param name="entry">The corresponding loading collection entry </param>
		/// <remarks>
		/// This xref map is used because sometimes a collection is in process of
		/// being loaded from one result set, but needs to be accessed from the
		/// context of another "nested" result set processing.
		/// Implementation note: package protected, as this is meant solely for use
		/// by {@link CollectionLoadContext} to be able to locate collections
		/// being loaded by other {@link CollectionLoadContext}s/{@link ResultSet}s.
		/// </remarks>
		internal void RegisterLoadingCollectionXRef(CollectionKey entryKey, LoadingCollectionEntry entry)
		{
			if (xrefLoadingCollectionEntries == null)
				xrefLoadingCollectionEntries = new Dictionary<CollectionKey, LoadingCollectionEntry>();

			xrefLoadingCollectionEntries[entryKey] = entry;
		}