protected IPrefetchState EnsureInitializedRelationsIntern2(Object objects, ILinkedMap <Type, PrefetchPath[]> entityTypeToPrefetchPath) { bool setCreated = false; try { AlreadyHandledSet alreadyHandledSet = alreadyHandledSetTL.Value; if (alreadyHandledSet == null) { alreadyHandledSet = new AlreadyHandledSet(); alreadyHandledSetTL.Value = alreadyHandledSet; setCreated = true; } IEntityMetaDataProvider entityMetaDataProvider = this.EntityMetaDataProvider; ValueHolderContainerMixin valueHolderContainerMixin = this.ValueHolderContainerMixin; IdentityLinkedMap <ICacheIntern, IISet <IObjRef> > cacheToOrisLoadedHistory = new IdentityLinkedMap <ICacheIntern, IISet <IObjRef> >(); IdentityLinkedMap <ICacheIntern, IISet <IObjRelation> > cacheToOrelsLoadedHistory = new IdentityLinkedMap <ICacheIntern, IISet <IObjRelation> >(); IdentityLinkedMap <ICacheIntern, IISet <IObjRef> > cacheToOrisToLoad = new IdentityLinkedMap <ICacheIntern, IISet <IObjRef> >(); IdentityLinkedMap <ICacheIntern, IMap <IObjRelation, bool> > cacheToOrelsToLoad = new IdentityLinkedMap <ICacheIntern, IMap <IObjRelation, bool> >(); List <PrefetchCommand> loadItems = new List <PrefetchCommand>(); HandleObjects(objects, entityTypeToPrefetchPath, alreadyHandledSet, cacheToOrisLoadedHistory, cacheToOrelsLoadedHistory, cacheToOrisToLoad, cacheToOrelsToLoad, loadItems); // Remove all oris which have already been tried to load before if (cacheToOrisToLoad.Count == 0 && cacheToOrelsToLoad.Count == 0) { // No ori remaining which makes sense to try to load if (setCreated) { return(new PrefetchState(alreadyHandledSet)); } return(null); } List <Object> hardRefList = new List <Object>(); // Store hard-ref-list to global hard ref alreadyHandledSet.Put(hardRefList, null, true); ProcessPendingOrelsAndObjRefs(entityTypeToPrefetchPath, alreadyHandledSet, cacheToOrisLoadedHistory, cacheToOrelsLoadedHistory, cacheToOrisToLoad, cacheToOrelsToLoad, loadItems, hardRefList); // No ori remaining which makes sense to try to load if (setCreated) { return(new PrefetchState(alreadyHandledSet)); } return(null); } finally { if (setCreated) { alreadyHandledSetTL.Value = null; } } }
protected bool HandleValueHolder(DirectValueHolderRef vhr, PrefetchPath[] cachePaths, IMap <ICacheIntern, IISet <IObjRef> > cacheToOrisToLoad, IMap <ICacheIntern, IMap <IObjRelation, bool> > cacheToOrelsToLoad, IMap <ICacheIntern, IISet <IObjRef> > cacheToOrisLoadedHistory, IMap <ICacheIntern, IISet <IObjRelation> > cacheToOrelsLoadedHistory, AlreadyHandledSet alreadyHandledSet, IList <PrefetchCommand> cascadeLoadItems) { RelationMember member = vhr.Member; bool newOriToLoad = false; if (vhr is IndirectValueHolderRef) { RootCacheValue rcv = (RootCacheValue)vhr.Vhc; ICacheIntern rootCache = ((IndirectValueHolderRef)vhr).RootCache; IEntityMetaData metaData = EntityMetaDataProvider.GetMetaData(rcv.EntityType); int relationIndex = metaData.GetIndexByRelation(member); IObjRef[] rcvObjRefs = rcv.GetRelation(relationIndex); if (rcvObjRefs == null) { IObjRelation self = ValueHolderContainerMixin.GetSelf(rcv, member.Name); ISet <IObjRelation> orelsLoadedHistory = cacheToOrelsLoadedHistory.Get(rootCache); if (orelsLoadedHistory == null || !orelsLoadedHistory.Contains(self)) { IMap <IObjRelation, bool> orelsToLoad = cacheToOrelsToLoad.Get(rootCache); if (orelsToLoad == null) { orelsToLoad = new HashMap <IObjRelation, bool>(); cacheToOrelsToLoad.Put(rootCache, orelsToLoad); } orelsToLoad.Put(self, vhr.ObjRefsOnly); AddCascadeLoadItem(vhr, cachePaths, cascadeLoadItems); } return(false); } else if (!vhr.ObjRefsOnly && rcvObjRefs.Length > 0) { ISet <IObjRef> orisLoadedHistory = cacheToOrisLoadedHistory.Get(rootCache); for (int b = rcvObjRefs.Length; b-- > 0;) { IObjRef ori = rcvObjRefs[b]; if (orisLoadedHistory != null && orisLoadedHistory.Contains(ori)) { // Object has been tried to load before but it is obviously not in the cache // So the load must have been failed somehow. It is assumed that the entity // is not persisted in the database anymore (deleted before) so the ORI is illegal. // We cleanup the ValueHolder so that future calls will not lead to // another unnecessary roundtrip to the server rcvObjRefs[b] = null; continue; } IISet <IObjRef> orisToLoad = cacheToOrisToLoad.Get(rootCache); if (orisToLoad == null) { orisToLoad = new CHashSet <IObjRef>(); cacheToOrisToLoad.Put(rootCache, orisToLoad); } orisToLoad.Add(ori); newOriToLoad = true; } if (newOriToLoad) { AddCascadeLoadItem(vhr, cachePaths, cascadeLoadItems); } } return(false); } IValueHolderContainer vhc = (IValueHolderContainer)vhr.Vhc; int relationIndex2 = vhc.Get__EntityMetaData().GetIndexByRelationName(member.Name); if (ValueHolderState.INIT == vhc.Get__State(relationIndex2)) { return(true); } ICacheIntern cache = vhc.__TargetCache; IObjRef[] objRefs = vhc.Get__ObjRefs(relationIndex2); if (objRefs == null) { IObjRelation self = vhc.Get__Self(relationIndex2); List <IObjRelation> orels = new List <IObjRelation>(); orels.Add(self); IList <IObjRelationResult> orelResults = cache.GetObjRelations(orels, cache, failEarlyReturnMisses); IObjRelationResult orelResult = orelResults[0]; if (orelResult == null) { ISet <IObjRelation> orelsLoadedHistory = cacheToOrelsLoadedHistory.Get(cache); if (orelsLoadedHistory == null || !orelsLoadedHistory.Contains(self)) { IMap <IObjRelation, bool> orelsToLoad = cacheToOrelsToLoad.Get(cache); if (orelsToLoad == null) { orelsToLoad = new HashMap <IObjRelation, bool>(); cacheToOrelsToLoad.Put(cache, orelsToLoad); } orelsToLoad.Put(self, vhr.ObjRefsOnly); AddCascadeLoadItem(vhr, cachePaths, cascadeLoadItems); } return(false); } objRefs = orelResult.Relations; if (objRefs != null) { vhc.Set__ObjRefs(relationIndex2, objRefs); } } if (!vhr.ObjRefsOnly && objRefs != null && objRefs.Length > 0) { IList <Object> loadedObjects = cache.GetObjects(new List <IObjRef>(objRefs), cache, failEarlyReturnMisses); try { for (int b = objRefs.Length; b-- > 0;) { IObjRef ori = objRefs[b]; Object loadedObject = loadedObjects[b]; if (loadedObject != null) { continue; } ISet <IObjRef> orisLoadedHistory = cacheToOrisLoadedHistory.Get(cache); if (orisLoadedHistory != null && orisLoadedHistory.Contains(ori)) { // Object has been tried to load before but it is obviously not in the cache // So the load must have been failed somehow. It is assumed that the entity // is not persisted in the database anymore (deleted before) so the ORI is illegal. // We cleanup the ValueHolder so that future calls will not lead to // another unnecessary roundtrip to the server objRefs[b] = null; continue; } IISet <IObjRef> orisToLoad = cacheToOrisToLoad.Get(cache); if (orisToLoad == null) { orisToLoad = new CHashSet <IObjRef>(); cacheToOrisToLoad.Put(cache, orisToLoad); } orisToLoad.Add(ori); newOriToLoad = true; } } finally { loadedObjects.Clear(); loadedObjects = null; } } if (objRefs == null || newOriToLoad) { AddCascadeLoadItem(vhr, cachePaths, cascadeLoadItems); return(false); } return(true); }
protected void ProcessPendingOrelsAndObjRefs(ILinkedMap <Type, PrefetchPath[]> entityTypeToPrefetchPath, AlreadyHandledSet alreadyHandledSet, IdentityLinkedMap <ICacheIntern, IISet <IObjRef> > cacheToOrisLoadedHistory, IdentityLinkedMap <ICacheIntern, IISet <IObjRelation> > cacheToOrelsLoadedHistory, IdentityLinkedMap <ICacheIntern, IISet <IObjRef> > cacheToOrisToLoad, IdentityLinkedMap <ICacheIntern, IMap <IObjRelation, bool> > cacheToOrelsToLoad, List <PrefetchCommand> pendingPrefetchCommands, List <Object> hardRefList) { // all relation members where at least one instance of the owning entity type needs a prefetch on this member in the immediate next step MergePrefetchPathsCache mergePrefetchPathsCache = new MergePrefetchPathsCache(EntityMetaDataProvider); IdentityLinkedSet <Member> prioMembers = PrioMembersProvider.GetPrioMembers(entityTypeToPrefetchPath, pendingPrefetchCommands, mergePrefetchPathsCache); LoadAndAddOrels(cacheToOrelsToLoad, hardRefList, cacheToOrelsLoadedHistory, cacheToOrisToLoad, prioMembers); LoadAndAddOris(cacheToOrisToLoad, hardRefList, cacheToOrisLoadedHistory); while (pendingPrefetchCommands.Count > 0) { PrefetchCommand[] currentPrefetchCommands = pendingPrefetchCommands.ToArray(); // Clear the items to be ready for cascaded items in new batch recursion step pendingPrefetchCommands.Clear(); if (prioMembers.Count > 0) { for (int a = 0, size = currentPrefetchCommands.Length; a < size; a++) { PrefetchCommand prefetchCommand = currentPrefetchCommands[a]; DirectValueHolderRef valueHolder = prefetchCommand.valueHolder; if (!prioMembers.Contains(valueHolder.Member)) { currentPrefetchCommands[a] = null; pendingPrefetchCommands.Add(prefetchCommand); } } } GuiThreadHelper.InvokeInGuiAndWait(delegate() { ICacheModification cacheModification = CacheModification; ValueHolderContainerMixin valueHolderContainerMixin = ValueHolderContainerMixin; bool oldActive = cacheModification.Active; if (!oldActive) { cacheModification.Active = true; } try { foreach (PrefetchCommand prefetchCommand in currentPrefetchCommands) { if (prefetchCommand == null) { continue; } DirectValueHolderRef valueHolder = prefetchCommand.valueHolder; PrefetchPath[] cachePaths = prefetchCommand.prefetchPaths; RelationMember member = valueHolder.Member; // Merge the root prefetch path with the relative prefetch path cachePaths = mergePrefetchPathsCache.MergePrefetchPaths(member.ElementType, cachePaths, entityTypeToPrefetchPath); IObjRefContainer vhc = valueHolder.Vhc; ICacheIntern targetCache; bool doSetValue = false; if (valueHolder is IndirectValueHolderRef) { IndirectValueHolderRef valueHolderKey = (IndirectValueHolderRef)valueHolder; targetCache = valueHolderKey.RootCache; } else { targetCache = ((IValueHolderContainer)vhc).__TargetCache; doSetValue = true; } int relationIndex = vhc.Get__EntityMetaData().GetIndexByRelation(member); IObjRef[] objRefs = vhc.Get__ObjRefs(relationIndex); Object obj = valueHolderContainerMixin.GetValue(vhc, relationIndex, member, targetCache, objRefs, CacheDirective.FailEarly); if (doSetValue && obj != null) { member.SetValue(vhc, obj); } EnsureInitializedRelationsIntern3(obj, cachePaths, entityTypeToPrefetchPath, cacheToOrisToLoad, cacheToOrelsToLoad, cacheToOrisLoadedHistory, cacheToOrelsLoadedHistory, alreadyHandledSet, pendingPrefetchCommands); } } finally { if (!oldActive) { cacheModification.Active = false; } } }); // Remove all oris which have already been tried to load before if (cacheToOrisToLoad.Count == 0 && cacheToOrelsToLoad.Count == 0 && pendingPrefetchCommands.Count == 0) { return; } prioMembers = PrioMembersProvider.GetPrioMembers(entityTypeToPrefetchPath, pendingPrefetchCommands, mergePrefetchPathsCache); LoadAndAddOrels(cacheToOrelsToLoad, hardRefList, cacheToOrelsLoadedHistory, cacheToOrisToLoad, prioMembers); LoadAndAddOris(cacheToOrisToLoad, hardRefList, cacheToOrisLoadedHistory); } }