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); } }
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); }
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); } } } }
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)); }
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); } } }
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); } }
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); } } } }
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)); }
public DirectValueHolderRef(IObjRefContainer vhc, RelationMember member, bool objRefsOnly) { this.vhc = vhc; this.member = member; this.objRefsOnly = objRefsOnly; }
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); })); }
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; } }
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); } }