예제 #1
0
        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);
            }
        }
예제 #2
0
        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));
        }