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