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); } }
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)); }