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; } } }
/// <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; }
/// <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); }
/// <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; }