예제 #1
0
        public IObjRef[][] ExtractRelations(IEntityMetaData metaData, Object obj, IList <Object> relationValues)
        {
            RelationMember[] relationMembers = metaData.RelationMembers;

            if (relationMembers.Length == 0)
            {
                return(ObjRef.EMPTY_ARRAY_ARRAY);
            }
            IValueHolderContainer vhc = (IValueHolderContainer)obj;

            IObjRef[][] relations = new IObjRef[relationMembers.Length][];

            IObjRefHelper objRefHelper = this.ObjRefHelper;

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

                if (ValueHolderState.INIT != vhc.Get__State(relationIndex))
                {
                    relations[relationIndex] = vhc.Get__ObjRefs(relationIndex);
                    continue;
                }
                Object relationValue = relationMember.GetValue(obj, false);
                if (relationValue == null)
                {
                    relations[relationIndex] = ObjRef.EMPTY_ARRAY;
                    continue;
                }
                IList <IObjRef> oris = objRefHelper.ExtractObjRefList(relationValue, null);
                relations[relationIndex] = oris != null?ListUtil.ToArray <IObjRef>(oris) : null;

                if (relationValues != null)
                {
                    relationValues.Add(relationValue);
                }
            }
            return(relations);
        }
예제 #2
0
        protected void EnsureInitializedRelationsIntern3(Object obj, PrefetchPath[] cachePaths, ILinkedMap <Type, PrefetchPath[]> entityTypeToPrefetchPaths,
                                                         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)
        {
            if (obj == null)
            {
                return;
            }
            if (!alreadyHandledSet.PutIfNotExists(obj, cachePaths, true))
            {
                return;
            }
            if (obj is IndirectValueHolderRef)
            {
                IndirectValueHolderRef vhk = (IndirectValueHolderRef)obj;
                HandleValueHolder(vhk, cachePaths, cacheToOrisToLoad, cacheToOrelsToLoad, cacheToOrisLoadedHistory, cacheToOrelsLoadedHistory,
                                  alreadyHandledSet, cascadeLoadItems);
                // Do nothing because this is only to prefetch RootCache entries
                return;
            }
            else if (obj is DirectValueHolderRef)
            {
                DirectValueHolderRef vhk = (DirectValueHolderRef)obj;
                if (!HandleValueHolder(vhk, cachePaths, cacheToOrisToLoad, cacheToOrelsToLoad, cacheToOrisLoadedHistory, cacheToOrelsLoadedHistory,
                                       alreadyHandledSet, cascadeLoadItems))
                {
                    return;
                }
                // force valueholder init. at this point we know that all related items are already in the cache. there will be no roundtrip
                // to the server
                if (vhk.Member == null)
                {
                    obj = vhk.Vhc;
                }
                else
                {
                    obj = vhk.Member.GetValue(vhk.Vhc);
                }
            }
            if (obj == null)
            {
                // this check is necessary because even if we create only instances of DirectValueHolderRef in cases where there is a not initalized relation
                // even then it might be possible that a concurrent thread initializes the valueholder to null (e.g. an empty to-one relation)
                return;
            }
            if ((cachePaths == null || cachePaths.Length == 0) && entityTypeToPrefetchPaths == null)
            {
                return;
            }
            if (obj is IEnumerable)
            {
                var items = new List <Object>();
                foreach (Object item in (IEnumerable)obj)
                {
                    if (item == null)
                    {
                        continue;
                    }
                    items.Add(item);
                }
                foreach (Object item in items)
                {
                    EnsureInitializedRelationsIntern3(item, cachePaths, entityTypeToPrefetchPaths, cacheToOrisToLoad, cacheToOrelsToLoad,
                                                      cacheToOrisLoadedHistory, cacheToOrelsLoadedHistory, alreadyHandledSet, cascadeLoadItems);
                }
                return;
            }
            IEntityMetaData metaData = ((IEntityMetaDataHolder)obj).Get__EntityMetaData();

            if (cachePaths == null || cachePaths.Length == 0)
            {
                if (entityTypeToPrefetchPaths != null)
                {
                    cachePaths = entityTypeToPrefetchPaths.Get(metaData.EntityType);
                }
                if (cachePaths == null || cachePaths.Length == 0)
                {
                    return;
                }
            }
            RelationMember[] relationMembers = metaData.RelationMembers;
            if (relationMembers.Length == 0)
            {
                return;
            }
            IValueHolderContainer vhc = (IValueHolderContainer)obj;

            for (int a = cachePaths.Length; a-- > 0;)
            {
                PrefetchPath path = cachePaths[a];

                int            relationIndex = path.memberIndex;
                RelationMember member        = relationMembers[relationIndex];

                if (ValueHolderState.INIT != vhc.Get__State(relationIndex))
                {
                    DirectValueHolderRef vhk = new DirectValueHolderRef(vhc, member);
                    EnsureInitializedRelationsIntern3(vhk, path.children, entityTypeToPrefetchPaths, cacheToOrisToLoad, cacheToOrelsToLoad, cacheToOrisLoadedHistory,
                                                      cacheToOrelsLoadedHistory, alreadyHandledSet, cascadeLoadItems);
                    continue;
                }
                Object memberValue = member.GetValue(obj);
                if (memberValue == null)
                {
                    continue;
                }
                EnsureInitializedRelationsIntern3(memberValue, path.children, entityTypeToPrefetchPaths, cacheToOrisToLoad, cacheToOrelsToLoad,
                                                  cacheToOrisLoadedHistory, cacheToOrelsLoadedHistory, alreadyHandledSet, cascadeLoadItems);
            }
        }
예제 #3
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);
        }
예제 #4
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);
                }
            }
        }