Exemplo n.º 1
0
        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);
        }
Exemplo n.º 2
0
        protected void HandleValueHolderContainer(IValueHolderContainer vhc, RelationMember[] relationMembers, IObjRef[][] relations)
        {
            ICacheHelper cacheHelper = this.CacheHelper;
            ICacheIntern parent      = this.Parent;
            IProxyHelper proxyHelper = this.ProxyHelper;

            for (int relationIndex = relationMembers.Length; relationIndex-- > 0;)
            {
                RelationMember relationMember    = relationMembers[relationIndex];
                IObjRef[]      relationsOfMember = relations[relationIndex];

                if (!CascadeLoadMode.EAGER.Equals(relationMember.CascadeLoadMode))
                {
                    if (ValueHolderState.INIT != vhc.Get__State(relationIndex))
                    {
                        // Update ObjRef information within the entity and do nothing else
                        vhc.Set__ObjRefs(relationIndex, relationsOfMember);
                        continue;
                    }
                }
                // We can safely access to relation if we want to
                if (relationsOfMember == null)
                {
                    // Reset value holder state because we do not know the content currently
                    vhc.Set__Uninitialized(relationIndex, null);
                    continue;
                }
                Object relationValue = relationMember.GetValue(vhc);
                if (relationsOfMember.Length == 0)
                {
                    if (!relationMember.IsToMany)
                    {
                        if (relationValue != null)
                        {
                            // Relation has to be flushed
                            relationMember.SetValue(vhc, null);
                        }
                    }
                    else
                    {
                        if (relationValue != null)
                        {
                            // Reuse existing collection
                            ListUtil.ClearList(relationValue);
                        }
                        else
                        {
                            // We have to create a new empty collection
                            relationValue = cacheHelper.CreateInstanceOfTargetExpectedType(relationMember.RealType, relationMember.ElementType);
                            relationMember.SetValue(vhc, relationValue);
                        }
                    }
                    continue;
                }
                // So we know the new content (which is not empty) and we know that the current content is already initialized
                // Now we have to refresh the current content eagerly

                // load entities as if we were an "eager valueholder" here
                IList <Object> potentialNewItems = parent.GetObjects(new List <IObjRef>(relationsOfMember), this, CacheDirective.None);
                if (OverwriteToManyRelations)
                {
                    Object newRelationValue = cacheHelper.ConvertResultListToExpectedType(potentialNewItems, relationMember.RealType,
                                                                                          relationMember.ElementType);
                    // Set new to-many-relation, even if there has not changed anything in its item content
                    relationMember.SetValue(vhc, newRelationValue);
                    continue;
                }
                IList <Object> relationItems = ListUtil.AnyToList(relationValue);

                bool diff = (relationItems.Count != potentialNewItems.Count);
                if (!diff)
                {
                    for (int b = potentialNewItems.Count; b-- > 0;)
                    {
                        if (!Object.ReferenceEquals(potentialNewItems[b], relationItems[b]))
                        {
                            diff = true;
                            break;
                        }
                    }
                }
                if (!diff)
                {
                    // Nothing to do
                    continue;
                }
                if (relationValue != null && relationMember.IsToMany)
                {
                    // Reuse existing collection
                    ListUtil.ClearAndFillList(relationValue, relationItems);
                }
                else
                {
                    // We have to create a new empty collection or replace the to-one value
                    Object newRelationValue = cacheHelper.ConvertResultListToExpectedType(potentialNewItems, relationMember.RealType,
                                                                                          relationMember.ElementType);
                    relationMember.SetValue(vhc, newRelationValue);
                }
            }
        }