コード例 #1
0
        protected void ScanForInitializedObjects(Object obj, ISet <Object> alreadyScannedObjects, ISet <IObjRef> objRefs)
        {
            if (obj == null || !alreadyScannedObjects.Add(obj))
            {
                return;
            }
            if (obj is IList)
            {
                IList list = (IList)obj;
                for (int a = list.Count; a-- > 0;)
                {
                    Object item = list[a];
                    ScanForInitializedObjects(item, alreadyScannedObjects, objRefs);
                }
                return;
            }
            if (obj is IEnumerable)
            {
                foreach (Object item in (IEnumerable)obj)
                {
                    ScanForInitializedObjects(item, alreadyScannedObjects, objRefs);
                }
                return;
            }
            IEntityMetaData metaData = ((IEntityMetaDataHolder)obj).Get__EntityMetaData();
            Object          id       = metaData.IdMember.GetValue(obj, false);

            if (id == null)
            {
                // This may happen if a normally retrieved object gets deleted and therefore has lost its primary id
                // TODO: The object is still contained in the cache, maybe this should be reviewed
                return;
            }
            ObjRef objRef = new ObjRef(metaData.EntityType, ObjRef.PRIMARY_KEY_INDEX, id, null);

            objRefs.Add(objRef);
            RelationMember[] relationMembers = metaData.RelationMembers;
            if (relationMembers.Length == 0)
            {
                return;
            }
            IObjRefContainer vhc = (IObjRefContainer)obj;

            for (int relationIndex = relationMembers.Length; relationIndex-- > 0;)
            {
                RelationMember relationMember = relationMembers[relationIndex];
                if (ValueHolderState.INIT != vhc.Get__State(relationIndex))
                {
                    continue;
                }
                Object value = relationMember.GetValue(obj, false);
                ScanForInitializedObjects(value, alreadyScannedObjects, objRefs);
            }
        }
コード例 #2
0
        protected override void PutInternObjRelation(Object cacheValue, IEntityMetaData metaData, IObjRelation objRelation, IObjRef[] relationsOfMember)
        {
            int relationIndex    = metaData.GetIndexByRelationName(objRelation.MemberName);
            IObjRefContainer vhc = (IObjRefContainer)cacheValue;

            if (ValueHolderState.INIT == vhc.Get__State(relationIndex))
            {
                // It is not allowed to set ObjRefs for an already initialized relation
                return;
            }
            vhc.Set__ObjRefs(relationIndex, relationsOfMember);
        }
コード例 #3
0
        protected void CheckCascadeRefreshNeeded(CacheDependencyNode node)
        {
            CacheChangeItem[] cacheChangeItems = node.cacheChangeItems;
            if (cacheChangeItems == null)
            {
                return;
            }
            HashMap <IObjRef, CacheValueAndPrivilege> objRefToCacheValueMap = node.objRefToCacheValueMap;

            for (int c = cacheChangeItems.Length; c-- > 0;)
            {
                CacheChangeItem cci = cacheChangeItems[c];
                if (cci == null)
                {
                    continue;
                }
                IList <IObjRef> objectRefsToUpdate = cci.UpdatedObjRefs;
                IList <Object>  objectsToUpdate    = cci.UpdatedObjects;

                for (int a = objectRefsToUpdate.Count; a-- > 0;)
                {
                    IObjRef objRefToUpdate = objectRefsToUpdate[a];
                    Object  objectToUpdate = objectsToUpdate[a];
                    CacheValueAndPrivilege cacheValueAndPrivilege = objRefToCacheValueMap.Get(objRefToUpdate);
                    if (cacheValueAndPrivilege == null)
                    {
                        // Current value in childCache is not in our interest here
                        continue;
                    }
                    IEntityMetaData  metaData        = ((IEntityMetaDataHolder)objectToUpdate).Get__EntityMetaData();
                    RelationMember[] relationMembers = metaData.RelationMembers;
                    if (relationMembers.Length == 0)
                    {
                        continue;
                    }
                    RootCacheValue   cacheValue = cacheValueAndPrivilege.cacheValue;
                    IObjRefContainer vhc        = (IObjRefContainer)objectToUpdate;
                    for (int relationIndex = relationMembers.Length; relationIndex-- > 0;)
                    {
                        if (ValueHolderState.INIT != vhc.Get__State(relationIndex))
                        {
                            continue;
                        }
                        // the object which has to be updated has initialized relations. So we have to ensure
                        // that these relations are in the RootCache at the time the target object will be updated.
                        // This is because initialized relations have to remain initialized after update but the relations
                        // may have been updated, too
                        BatchPendingRelations(cacheValue, relationMembers[relationIndex], cacheValue.GetRelation(relationIndex), node);
                    }
                }
            }
        }
コード例 #4
0
        public void test_ValueHolderContainer_Embedded()
        {
            Material obj = EntityFactory.CreateEntity <Material>();

            // Test EmbMat.EmbMatType
            Assert.IsInstanceOfType(obj.EmbMat, typeof(IEmbeddedType));
            obj.EmbMat.Name = "Name2";
            Assert.AssertEquals("Name2", obj.EmbMat.Name);

            Assert.AssertEquals(0, ReflectUtil.GetDeclaredFieldInHierarchy(obj.GetType(), ValueHolderIEC.GetInitializedFieldName("EmbMat.EmbMatType")).Length);
            Assert.AssertEquals(1, ReflectUtil.GetDeclaredFieldInHierarchy(obj.EmbMat.GetType(), ValueHolderIEC.GetInitializedFieldName("EmbMatType")).Length);

            IObjRefContainer vhc = (IObjRefContainer)obj;

            IEntityMetaData metaData        = vhc.Get__EntityMetaData();
            int             embMatTypeIndex = metaData.GetIndexByRelationName("EmbMat.EmbMatType");

            Assert.AssertFalse(vhc.Is__Initialized(embMatTypeIndex));

            IObjRef[] emptyRefs = ObjRef.EMPTY_ARRAY;
            ((IObjRefContainer)obj).Set__ObjRefs(embMatTypeIndex, emptyRefs);
            IObjRef[] objRefs = vhc.Get__ObjRefs(embMatTypeIndex);
            Assert.AssertSame(emptyRefs, objRefs);

            Assert.AssertNull(obj.EmbMat.EmbMatType);
            Assert.AssertTrue(vhc.Is__Initialized(embMatTypeIndex));

            // Test EmbMat.EmbMat2.EmbMatType2
            Assert.IsInstanceOfType(obj.EmbMat.EmbMat2, typeof(IEmbeddedType));
            obj.EmbMat.EmbMat2.Name2 = "Name3";
            Assert.AssertEquals("Name3", obj.EmbMat.EmbMat2.Name2);

            Assert.AssertNull(obj.GetType().GetField(ValueHolderIEC.GetInitializedFieldName("EmbMat.EmbMat2.EmbMatType2")));
            Assert.AssertNull(obj.EmbMat.GetType().GetField(ValueHolderIEC.GetInitializedFieldName("EmbMat2.EmbMatType2")));
            Assert.AssertNotNull(obj.EmbMat.EmbMat2.GetType().GetField(ValueHolderIEC.GetInitializedFieldName("EmbMatType2")));

            embMatTypeIndex = metaData.GetIndexByRelationName("EmbMat.EmbMat2.EmbMatType2");

            Assert.AssertFalse(vhc.Is__Initialized(embMatTypeIndex));

            ((IObjRefContainer)obj).Set__ObjRefs(embMatTypeIndex, emptyRefs);
            objRefs = ((IObjRefContainer)obj).Get__ObjRefs(embMatTypeIndex);
            Assert.AssertSame(emptyRefs, objRefs);

            Assert.AssertNull(obj.EmbMat.EmbMat2.EmbMatType2);
            Assert.AssertTrue(vhc.Is__Initialized(embMatTypeIndex));

            // Test EmbMat3.EmbMatType
            Assert.IsInstanceOfType(obj.EmbMat3, typeof(IEmbeddedType));
        }
コード例 #5
0
ファイル: MergeController.cs プロジェクト: vogelb/ambeth
        protected virtual void Persist(Object obj, MergeHandle handle)
        {
            IEntityMetaData metaData = ((IEntityMetaDataHolder)obj).Get__EntityMetaData();

            AddModification(obj, handle); // Ensure entity will be persisted even if no single property is specified

            RelationMember[] relationMembers = metaData.RelationMembers;
            if (relationMembers.Length > 0)
            {
                IObjRefContainer vhc = (IObjRefContainer)obj;
                for (int relationIndex = relationMembers.Length; relationIndex-- > 0;)
                {
                    RelationMember relationMember = relationMembers[relationIndex];
                    if (ValueHolderState.INIT != vhc.Get__State(relationIndex))
                    {
                        continue;
                    }
                    Object objMember = relationMember.GetValue(obj, false);

                    if (objMember == null)
                    {
                        continue;
                    }
                    AddOriModification(obj, relationMember.Name, objMember, null, handle);
                }
            }
            foreach (PrimitiveMember primitiveMember in metaData.PrimitiveMembers)
            {
                if (primitiveMember.TechnicalMember)
                {
                    continue;
                }
                Object objMember = primitiveMember.GetValue(obj, true);

                if (objMember != null)
                {
                    AddModification(obj, primitiveMember.Name, primitiveMember.ElementType, objMember, null, handle);
                }
            }
        }
コード例 #6
0
ファイル: MergeCommand.cs プロジェクト: vogelb/ambeth
        protected void ApplyRelationUpdateItems(IObjRefContainer entity, IRelationUpdateItem[] ruis, bool isUpdate, IEntityMetaData metadata, IReader reader)
        {
            List <Object> toPrefetch = new List <Object>();

            RelationMember[] relationMembers = metadata.RelationMembers;
            foreach (IRelationUpdateItem rui in ruis)
            {
                String memberName    = rui.MemberName;
                int    relationIndex = metadata.GetIndexByRelationName(memberName);
                if (ValueHolderState.INIT == entity.Get__State(relationIndex))
                {
                    throw new Exception("ValueHolder already initialized for property '" + memberName + "'");
                }

                IObjRef[] existingORIs = entity.Get__ObjRefs(relationIndex);
                IObjRef[] addedORIs    = rui.AddedORIs;
                IObjRef[] removedORIs  = rui.RemovedORIs;

                IObjRef[] newORIs;
                if (existingORIs.Length == 0)
                {
                    if (removedORIs != null && addedORIs.Length > 0)
                    {
                        throw new ArgumentException("Removing from empty member");
                    }
                    newORIs = addedORIs != null && addedORIs.Length > 0 ? addedORIs : ObjRef.EMPTY_ARRAY;
                }
                else
                {
                    // Set to efficiently remove entries
                    LinkedHashSet <IObjRef> existingORIsSet = new LinkedHashSet <IObjRef>(existingORIs);
                    if (removedORIs != null && removedORIs.Length > 0)
                    {
                        foreach (IObjRef removedORI in removedORIs)
                        {
                            if (!existingORIsSet.Remove(removedORI))
                            {
                                throw OptimisticLockUtil.ThrowModified(OriHelper.EntityToObjRef(entity), null, entity);
                            }
                        }
                    }
                    if (addedORIs != null && addedORIs.Length > 0)
                    {
                        foreach (IObjRef addedORI in addedORIs)
                        {
                            if (!existingORIsSet.Add(addedORI))
                            {
                                throw OptimisticLockUtil.ThrowModified(OriHelper.EntityToObjRef(entity), null, entity);
                            }
                        }
                    }
                    if (existingORIsSet.Count == 0)
                    {
                        newORIs = ObjRef.EMPTY_ARRAY;
                    }
                    else
                    {
                        newORIs = existingORIsSet.ToArray();
                    }
                }

                RelationMember member = relationMembers[relationIndex];
                if (isUpdate)
                {
                    entity.Set__ObjRefs(relationIndex, newORIs);
                    if (!entity.Is__Initialized(relationIndex))
                    {
                        DirectValueHolderRef dvhr = new DirectValueHolderRef(entity, member);
                        toPrefetch.Add(dvhr);
                    }
                }
                else
                {
                    BuildSetterCommands(entity, newORIs, member, reader);
                }
            }
            if (toPrefetch.Count > 0)
            {
                IObjectFuture  objectFuture = new PrefetchFuture(toPrefetch);
                IObjectCommand command      = CommandBuilder.Build(reader.CommandTypeRegistry, objectFuture, null);
                reader.AddObjectCommand(command);
            }
        }
コード例 #7
0
ファイル: MergeController.cs プロジェクト: vogelb/ambeth
        protected virtual void Merge(Object obj, Object clone, MergeHandle handle)
        {
            IEntityMetaDataProvider entityMetaDataProvider = this.EntityMetaDataProvider;
            IEntityMetaData         metaData = ((IEntityMetaDataHolder)obj).Get__EntityMetaData();

            bool fieldBasedMergeActive = handle.FieldBasedMergeActive;
            bool oneChangeOccured      = false;

            try
            {
                RelationMember[] relationMembers = metaData.RelationMembers;
                if (relationMembers.Length > 0)
                {
                    IObjRefContainer vhc = (IObjRefContainer)obj;
                    for (int relationIndex = relationMembers.Length; relationIndex-- > 0;)
                    {
                        RelationMember relationMember = relationMembers[relationIndex];
                        if (!metaData.IsMergeRelevant(relationMember))
                        {
                            continue;
                        }
                        if (ValueHolderState.INIT != vhc.Get__State(relationIndex))
                        {
                            // v2 valueholder is not initialized. so a change is impossible
                            continue;
                        }
                        Object objMember   = relationMember.GetValue(obj, false);
                        Object cloneMember = relationMember.GetValue(clone, false);
                        if (objMember is IDataObject && !((IDataObject)objMember).HasPendingChanges)
                        {
                            IEntityMetaData relationMetaData = entityMetaDataProvider.GetMetaData(relationMember.RealType);
                            if (EqualsReferenceOrId(objMember, cloneMember, handle, relationMetaData))
                            {
                                continue;
                            }
                        }

                        IEntityMetaData childMetaData = entityMetaDataProvider.GetMetaData(relationMember.ElementType);

                        if (IsMemberModified(objMember, cloneMember, handle, childMetaData))
                        {
                            oneChangeOccured = true;
                            AddOriModification(obj, relationMember.Name, objMember, cloneMember, handle);
                        }
                    }
                }
                if (fieldBasedMergeActive)
                {
                    MergePrimitivesFieldBased(metaData, obj, clone, handle);
                    return;
                }
                bool additionalRound;
                do
                {
                    additionalRound = !oneChangeOccured;
                    foreach (PrimitiveMember primitiveMember in metaData.PrimitiveMembers)
                    {
                        if (!metaData.IsMergeRelevant(primitiveMember))
                        {
                            continue;
                        }
                        Object objValue = primitiveMember.GetValue(obj, true);
                        if (oneChangeOccured)
                        {
                            AddModification(obj, primitiveMember.Name, primitiveMember.ElementType, objValue, null, handle);
                            continue;
                        }
                        Object cloneValue = primitiveMember.GetValue(clone, true);
                        if (!ArePrimitivesEqual(metaData, primitiveMember, objValue, cloneValue, handle))
                        {
                            oneChangeOccured = true;
                            break;
                        }
                    }
                }while (additionalRound && oneChangeOccured);
            }
            finally
            {
                PrimitiveMember versionMember = metaData.VersionMember;
                if (oneChangeOccured && versionMember != null)
                {
                    // Check for early optimistic locking (Another, later level is directly on persistence layer)
                    Object versionToMerge = versionMember.GetValue(obj, true);
                    Object currentVersion = versionMember.GetValue(clone, true);

                    int compareResult = ((IComparable)versionToMerge).CompareTo(currentVersion);
                    if (ExactVersionForOptimisticLockingRequired ? compareResult != 0 : compareResult < 0)
                    {
                        throw new OptimisticLockException(currentVersion, versionToMerge, obj);
                    }
                }
            }
        }
コード例 #8
0
ファイル: MergeController.cs プロジェクト: vogelb/ambeth
        protected void ScanForInitializedObjectsIntern(Object obj, bool isDeepMerge, IList <Object> objects, IMap <Type, IList <Object> > typeToObjectsToMerge,
                                                       ISet <Object> alreadyHandledObjectsSet, IList <IObjRef> objRefs, IList <ValueHolderRef> valueHolderKeys)
        {
            if (obj == null || !alreadyHandledObjectsSet.Add(obj))
            {
                return;
            }
            if (obj is IList)
            {
                IList list = (IList)obj;
                for (int a = 0, size = list.Count; a < size; a++)
                {
                    ScanForInitializedObjectsIntern(list[a], isDeepMerge, objects, typeToObjectsToMerge, alreadyHandledObjectsSet, objRefs, valueHolderKeys);
                }
                return;
            }
            else if (obj.GetType().IsArray)
            {
                Array array = (Array)obj;
                for (int a = array.Length; a-- > 0;)
                {
                    Object item = array.GetValue(a);
                    ScanForInitializedObjectsIntern(item, isDeepMerge, objects, typeToObjectsToMerge, alreadyHandledObjectsSet, objRefs, valueHolderKeys);
                }
                return;
            }
            else if (obj is IEnumerable && !(obj is String))
            {
                foreach (Object item in (IEnumerable)obj)
                {
                    ScanForInitializedObjectsIntern(item, isDeepMerge, objects, typeToObjectsToMerge, alreadyHandledObjectsSet, objRefs, valueHolderKeys);
                }
                return;
            }
            IEntityMetaData metaData = EntityMetaDataProvider.GetMetaData(obj.GetType(), true);

            if (metaData == null)
            {
                return;
            }
            IObjRef objRef = null;
            Object  id     = metaData.IdMember.GetValue(obj, false);

            if (id != null)
            {
                objRef = ObjRefFactory.CreateObjRef(metaData.EntityType, ObjRef.PRIMARY_KEY_INDEX, id, null);
                objRef.GetType().GetFields(BindingFlags.Instance | BindingFlags.NonPublic);
            }
            if (!(obj is IDataObject) || ((IDataObject)obj).HasPendingChanges)
            {
                if (typeToObjectsToMerge != null)
                {
                    IList <Object> objectsToMerge = typeToObjectsToMerge.Get(metaData.EntityType);
                    if (objectsToMerge == null)
                    {
                        objectsToMerge = new List <Object>();
                        typeToObjectsToMerge.Put(metaData.EntityType, objectsToMerge);
                    }
                    objectsToMerge.Add(obj);
                }
                objects.Add(obj);
                objRefs.Add(objRef);
            }
            if (!isDeepMerge)
            {
                return;
            }
            RelationMember[] relationMembers = metaData.RelationMembers;
            if (relationMembers.Length == 0)
            {
                return;
            }
            IObjRefContainer vhc = (IObjRefContainer)obj;

            for (int relationIndex = relationMembers.Length; relationIndex-- > 0;)
            {
                if (ValueHolderState.INIT != vhc.Get__State(relationIndex))
                {
                    continue;
                }
                RelationMember relationMember = relationMembers[relationIndex];
                Object         item           = relationMember.GetValue(obj);
                if (objRef != null && item != null)
                {
                    ValueHolderRef vhk = new ValueHolderRef(objRef, relationMember, relationIndex);
                    valueHolderKeys.Add(vhk);
                }
                ScanForInitializedObjectsIntern(item, isDeepMerge, objects, typeToObjectsToMerge, alreadyHandledObjectsSet, objRefs, valueHolderKeys);
            }
        }
コード例 #9
0
ファイル: MergeController.cs プロジェクト: vogelb/ambeth
        public virtual ICUDResult MergeDeep(Object obj, MergeHandle handle)
        {
            ICache cache = handle.Cache;

            if (cache == null && CacheFactory != null)
            {
                cache        = CacheFactory.Create(CacheFactoryDirective.NoDCE, false, false, "MergeController.ORIGINAL");
                handle.Cache = cache;
            }
            IMap <Type, IList <Object> > typeToObjectsToMerge = null;

            Type[] entityPersistOrder = EntityMetaDataProvider.GetEntityPersistOrder();
            if (entityPersistOrder != null && entityPersistOrder.Length > 0)
            {
                typeToObjectsToMerge = new HashMap <Type, IList <Object> >();
            }
            List <IObjRef>        objRefs                = new List <IObjRef>();
            List <ValueHolderRef> valueHolderKeys        = new List <ValueHolderRef>();
            IList <Object>        objectsToMerge         = ScanForInitializedObjects(obj, handle.IsDeepMerge, typeToObjectsToMerge, objRefs, valueHolderKeys);
            IList <Object>        eagerlyLoadedOriginals = null;

            // Load all requested object originals in one roundtrip
            if (objRefs.Count > 0)
            {
                eagerlyLoadedOriginals = cache.GetObjects(objRefs, CacheDirective.ReturnMisses);
                for (int a = eagerlyLoadedOriginals.Count; a-- > 0;)
                {
                    IObjRef existingOri = objRefs[a];
                    if (eagerlyLoadedOriginals[a] == null && existingOri != null && existingOri.Id != null)
                    {
                        // Cache miss for an entity we want to merge. This is an OptimisticLock-State
                        throw new OptimisticLockException(null, null, existingOri);
                    }
                }
                List <IObjRef> objRefsOfVhks = new List <IObjRef>(valueHolderKeys.Count);
                for (int a = 0, size = valueHolderKeys.Count; a < size; a++)
                {
                    objRefsOfVhks.Add(valueHolderKeys[a].ObjRef);
                }
                IList <Object> objectsOfVhks = cache.GetObjects(objRefsOfVhks, CacheDirective.FailEarly | CacheDirective.ReturnMisses);
                for (int a = valueHolderKeys.Count; a-- > 0;)
                {
                    IObjRefContainer objectOfVhk = (IObjRefContainer)objectsOfVhks[a];
                    if (objectOfVhk == null)
                    {
                        continue;
                    }
                    ValueHolderRef valueHolderRef = valueHolderKeys[a];
                    if (ValueHolderState.INIT != objectOfVhk.Get__State(valueHolderRef.RelationIndex))
                    {
                        DirectValueHolderRef vhcKey = new DirectValueHolderRef(objectOfVhk, valueHolderRef.Member);
                        handle.PendingValueHolders.Add(vhcKey);
                    }
                }
            }
            if (typeToObjectsToMerge != null)
            {
                foreach (Type orderedEntityType in entityPersistOrder)
                {
                    IList <Object> objectsToMergeOfOrderedType = typeToObjectsToMerge.Remove(orderedEntityType);
                    if (objectsToMergeOfOrderedType == null)
                    {
                        continue;
                    }
                    MergeDeepStart(objectsToMergeOfOrderedType, handle);
                }
                foreach (Entry <Type, IList <Object> > entry in typeToObjectsToMerge)
                {
                    IList <Object> objectsToMergeOfUnorderedType = entry.Value;
                    MergeDeepStart(objectsToMergeOfUnorderedType, handle);
                }
            }
            else if (objectsToMerge.Count > 0)
            {
                MergeDeepStart(objectsToMerge, handle);
            }
            return(CUDResultHelper.CreateCUDResult(handle));
        }
コード例 #10
0
 public DirectValueHolderRef(IObjRefContainer vhc, RelationMember member, bool objRefsOnly)
 {
     this.vhc         = vhc;
     this.member      = member;
     this.objRefsOnly = objRefsOnly;
 }
コード例 #11
0
        protected void ApplyRelationUpdateItem(IObjRefContainer entity, IRelationUpdateItem rui, bool isUpdate,
                                               IEntityMetaData metaData, IList <DirectValueHolderRef> toPrefetch, List <IObjRef> toFetchFromCache, bool checkBaseState,
                                               IList <IBackgroundWorkerDelegate> runnables)
        {
            IObjRefHelper  objRefHelper   = this.ObjRefHelper;
            String         memberName     = rui.MemberName;
            int            relationIndex  = metaData.GetIndexByRelationName(memberName);
            RelationMember relationMember = metaData.RelationMembers[relationIndex];

            IObjRef[] existingORIs;
            if (entity.Is__Initialized(relationIndex))
            {
                existingORIs = ListUtil.ToArray(ObjRefHelper.ExtractObjRefList(relationMember.GetValue(entity), null));
            }
            else
            {
                existingORIs = entity.Get__ObjRefs(relationIndex);
                if (existingORIs == null)
                {
                    toPrefetch.Add(new DirectValueHolderRef(entity, relationMember, true));
                    runnables.Add(new IBackgroundWorkerDelegate(delegate()
                    {
                        ApplyRelationUpdateItem(entity, rui, isUpdate, metaData, toPrefetch, toFetchFromCache, checkBaseState, runnables);
                    }));
                    return;
                }
            }
            IObjRef[] addedORIs   = rui.AddedORIs;
            IObjRef[] removedORIs = rui.RemovedORIs;

            IObjRef[] newORIs;
            if (existingORIs.Length == 0)
            {
                if (checkBaseState && removedORIs != null)
                {
                    throw new Exception("Removing from empty member");
                }
                newORIs = addedORIs != null ? (IObjRef[])addedORIs.Clone() : ObjRef.EMPTY_ARRAY;
                for (int a = newORIs.Length; a-- > 0;)
                {
                    newORIs[a] = CloneObjRef(newORIs[a], false);
                }
            }
            else
            {
                // Set to efficiently remove entries
                LinkedHashSet <IObjRef> existingORIsSet = new LinkedHashSet <IObjRef>(existingORIs);
                if (removedORIs != null)
                {
                    foreach (IObjRef removedORI in removedORIs)
                    {
                        IObjRef clonedObjRef = CloneObjRef(removedORI, false);
                        if (existingORIsSet.Remove(clonedObjRef) || !checkBaseState)
                        {
                            continue;
                        }
                        throw OptimisticLockUtil.ThrowModified(objRefHelper.EntityToObjRef(entity), null, entity);
                    }
                }
                if (addedORIs != null)
                {
                    foreach (IObjRef addedORI in addedORIs)
                    {
                        IObjRef clonedObjRef = CloneObjRef(addedORI, false);
                        if (existingORIsSet.Add(clonedObjRef) || !checkBaseState)
                        {
                            continue;
                        }
                        throw OptimisticLockUtil.ThrowModified(objRefHelper.EntityToObjRef(entity), null, entity);
                    }
                }
                if (existingORIsSet.Count == 0)
                {
                    newORIs = ObjRef.EMPTY_ARRAY;
                }
                else
                {
                    newORIs = existingORIsSet.ToArray();
                }
            }
            if (!entity.Is__Initialized(relationIndex))
            {
                entity.Set__ObjRefs(relationIndex, newORIs);
                return;
            }
            toFetchFromCache.AddRange(newORIs);
            runnables.Add(new IBackgroundWorkerDelegate(delegate()
            {
                ICache stateCache      = cloneStateTL.Value.incrementalState.GetStateCache();
                IList <Object> objects = stateCache.GetObjects(newORIs, CacheDirective.FailEarly);
                Object value;
                if (relationMember.IsToMany)
                {
                    // To-many relation
                    Object coll = ListUtil.CreateObservableCollectionOfType(relationMember.RealType, objects.Count);
                    ListUtil.FillList(coll, objects);
                    value = coll;
                }
                else
                {
                    // To-one relation
                    value = objects.Count > 0 ? objects[0] : null;
                }
                relationMember.SetValue(entity, value);
            }));
        }
コード例 #12
0
        protected ICUDResult ApplyIntern(ICUDResult cudResult, bool checkBaseState, IncrementalMergeState incrementalState)
        {
            ICache stateCache = incrementalState.GetStateCache();
            IList <IChangeContainer> allChanges   = cudResult.AllChanges;
            IList <Object>           originalRefs = cudResult.GetOriginalRefs();
            IList <Object>           allObjects   = GetAllExistingObjectsFromCache(stateCache, allChanges);
            List <Object>            hardRefs     = new List <Object>();

            hardRefs.Add(allObjects); // add list as item intended. adding each item of the source is NOT needed

            List <IObjRef> toFetchFromCache             = new List <IObjRef>();
            List <DirectValueHolderRef>      toPrefetch = new List <DirectValueHolderRef>();
            List <IBackgroundWorkerDelegate> runnables  = new List <IBackgroundWorkerDelegate>();

            IEntityFactory entityFactory = this.EntityFactory;

            IdentityHashMap <IObjRef, StateEntry> newObjRefToStateEntryMap        = new IdentityHashMap <IObjRef, StateEntry>();
            IdentityHashMap <IChangeContainer, IChangeContainer> alreadyClonedMap = new IdentityHashMap <IChangeContainer, IChangeContainer>();

            List <IChangeContainer> newAllChanges = new List <IChangeContainer>(allChanges.Count);

            for (int a = 0, size = allChanges.Count; a < size; a++)
            {
                IChangeContainer changeContainer = allChanges[a];
                Object           originalEntity  = originalRefs[a];

                StateEntry stateEntry = incrementalState.entityToStateMap.Get(originalEntity);

                IChangeContainer newChangeContainer;
                if (changeContainer is CreateContainer)
                {
                    newChangeContainer = new CreateContainer();
                }
                else if (changeContainer is UpdateContainer)
                {
                    newChangeContainer = new UpdateContainer();
                }
                else
                {
                    newChangeContainer = new DeleteContainer();
                }
                newAllChanges.Add(newChangeContainer);
                alreadyClonedMap.Put(changeContainer, newChangeContainer);

                if (!(changeContainer is CreateContainer))
                {
                    Object stateCacheEntity2 = allObjects[a];
                    stateEntry = incrementalState.entityToStateMap.Get(stateCacheEntity2);
                    if (stateEntry == null)
                    {
                        stateEntry = new StateEntry(stateCacheEntity2, changeContainer.Reference, incrementalState.entityToStateMap.Count + 1);

                        incrementalState.entityToStateMap.Put(stateCacheEntity2, stateEntry);
                        incrementalState.objRefToStateMap.Put(stateEntry.objRef, stateEntry);
                    }
                    // delete & update do not need further handling
                    continue;
                }
                Type realType = changeContainer.Reference.RealType;

                Object stateCacheEntity;
                if (stateEntry == null)
                {
                    stateCacheEntity = entityFactory.CreateEntity(realType);

                    DirectObjRef directObjRef = new DirectObjRef(realType, stateCacheEntity);
                    directObjRef.CreateContainerIndex = a;

                    stateEntry = new StateEntry(stateCacheEntity, directObjRef, incrementalState.entityToStateMap.Count + 1);

                    incrementalState.entityToStateMap.Put(stateCacheEntity, stateEntry);
                    incrementalState.objRefToStateMap.Put(stateEntry.objRef, stateEntry);
                    newObjRefToStateEntryMap.Put(changeContainer.Reference, stateEntry);
                }
                else
                {
                    stateCacheEntity = stateEntry.entity;
                }
                allObjects[a] = stateCacheEntity;
            }
            cloneStateTL.Value = new CloneState(newObjRefToStateEntryMap, incrementalState);
            try
            {
                for (int a = allChanges.Count; a-- > 0;)
                {
                    IChangeContainer changeContainer = allChanges[a];
                    IObjRefContainer entity          = (IObjRefContainer)allObjects[a];

                    changeContainer = FillClonedChangeContainer(changeContainer, alreadyClonedMap);

                    IPrimitiveUpdateItem[] puis;
                    IRelationUpdateItem[]  ruis;
                    if (changeContainer is CreateContainer)
                    {
                        CreateContainer createContainer = (CreateContainer)changeContainer;
                        puis = createContainer.Primitives;
                        ruis = createContainer.Relations;
                    }
                    else if (changeContainer is UpdateContainer)
                    {
                        UpdateContainer updateContainer = (UpdateContainer)changeContainer;
                        puis = updateContainer.Primitives;
                        ruis = updateContainer.Relations;
                    }
                    else
                    {
                        ((IDataObject)entity).ToBeDeleted = true;
                        continue;
                    }
                    IEntityMetaData metaData = ((IEntityMetaDataHolder)entity).Get__EntityMetaData();
                    ApplyPrimitiveUpdateItems(entity, puis, metaData);

                    if (ruis != null)
                    {
                        bool isUpdate = changeContainer is UpdateContainer;
                        foreach (IRelationUpdateItem rui in ruis)
                        {
                            ApplyRelationUpdateItem(entity, rui, isUpdate, metaData, toPrefetch, toFetchFromCache, checkBaseState, runnables);
                        }
                    }
                }
                while (toPrefetch.Count > 0 || toFetchFromCache.Count > 0 || runnables.Count > 0)
                {
                    if (toPrefetch.Count > 0)
                    {
                        PrefetchHelper.Prefetch(toPrefetch);
                        toPrefetch.Clear();
                    }
                    if (toFetchFromCache.Count > 0)
                    {
                        IList <Object> fetchedObjects = stateCache.GetObjects(toFetchFromCache, CacheDirective.None);
                        hardRefs.Add(fetchedObjects); // add list as item intended. adding each item of the source is NOT needed
                        toFetchFromCache.Clear();
                    }
                    IBackgroundWorkerDelegate[] runnableArray = runnables.ToArray();
                    runnables.Clear();
                    foreach (IBackgroundWorkerDelegate runnable in runnableArray)
                    {
                        runnable();
                    }
                }
                List <Object> newObjects = new List <Object>(allObjects.Count);
                List <DirectValueHolderRef> changedRelationRefs = new List <DirectValueHolderRef>();
                for (int a = allObjects.Count; a-- > 0;)
                {
                    IChangeContainer      newChange = newAllChanges[a];
                    IRelationUpdateItem[] ruis      = null;
                    Object entity = allObjects[a];
                    if (newChange is CreateContainer)
                    {
                        newObjects.Add(entity);
                        ruis = ((CreateContainer)newChange).Relations;
                    }
                    else if (newChange is UpdateContainer)
                    {
                        ruis = ((UpdateContainer)newChange).Relations;
                    }
                    if (ruis == null)
                    {
                        continue;
                    }
                    IEntityMetaData metaData = EntityMetaDataProvider.GetMetaData(entity.GetType());
                    foreach (IRelationUpdateItem rui in ruis)
                    {
                        Member member = metaData.GetMemberByName(rui.MemberName);
                        changedRelationRefs.Add(new DirectValueHolderRef((IObjRefContainer)entity, (RelationMember)member));
                    }
                }
                if (newObjects.Count > 0)
                {
                    ((IWritableCache)stateCache).Put(newObjects);
                }
                if (changedRelationRefs.Count > 0)
                {
                    PrefetchHelper.Prefetch(changedRelationRefs);
                }
                return(new CUDResult(newAllChanges, allObjects));
            }
            finally
            {
                cloneStateTL.Value = null;
            }
        }
コード例 #13
0
ファイル: CacheHelper.cs プロジェクト: vogelb/ambeth
        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);
            }
        }