Exemplo n.º 1
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);
            }));
        }