public IList <IObjRef> ExtractObjRefList(Object objValue, MergeHandle mergeHandle, IList <IObjRef> targetOriList, EntityCallback entityCallback) { if (objValue == null) { if (targetOriList == null) { targetOriList = new List <IObjRef>(0); } return(targetOriList); } if (objValue is IList) { IList list = (IList)objValue; if (targetOriList == null) { targetOriList = new List <IObjRef>(list.Count); } for (int a = 0, size = list.Count; a < size; a++) { Object objItem = list[a]; targetOriList.Add(GetCreateObjRef(objItem, mergeHandle)); if (entityCallback != null) { entityCallback(objItem); } } } else if (objValue is IEnumerable) { IEnumerator objEnumerator = ((IEnumerable)objValue).GetEnumerator(); if (targetOriList == null) { targetOriList = new List <IObjRef>(); } while (objEnumerator.MoveNext()) { Object objItem = objEnumerator.Current; targetOriList.Add(GetCreateObjRef(objItem, mergeHandle)); if (entityCallback != null) { entityCallback(objItem); } } } else { if (targetOriList == null) { targetOriList = new List <IObjRef>(1); } targetOriList.Add(GetCreateObjRef(objValue, mergeHandle)); if (entityCallback != null) { entityCallback(objValue); } } return(targetOriList); }
protected void MergeDeepStart(Object obj, MergeHandle handle) { if (handle.PendingValueHolders.Count > 0) { IList <Object> pendingValueHolders = handle.PendingValueHolders; PrefetchHelper.Prefetch(pendingValueHolders); pendingValueHolders.Clear(); } MergeDeepIntern(obj, handle); while (true) { IList <IBackgroundWorkerDelegate> pendingRunnables = handle.PendingRunnables; IList <Object> pendingValueHolders = handle.PendingValueHolders; if (pendingValueHolders.Count == 0 && pendingRunnables.Count == 0) { return; } if (pendingValueHolders.Count > 0) { PrefetchHelper.Prefetch(pendingValueHolders); pendingValueHolders.Clear(); } if (pendingRunnables.Count > 0) { IList <IBackgroundWorkerDelegate> pendingRunnablesClone = new List <IBackgroundWorkerDelegate>(pendingRunnables); for (int a = 0, size = pendingRunnablesClone.Count; a < size; a++) { pendingRunnablesClone[a].Invoke(); } } } }
protected void MergeDeepIntern(Object obj, MergeHandle handle) { if (obj == null) { return; } if (obj is IList) { if (!handle.alreadyProcessedSet.Add(obj)) { return; } IList objList = (IList)obj; for (int a = 0, size = objList.Count; a < size; a++) { MergeDeepIntern(objList[a], handle); } } else if (obj is IEnumerable) { if (!handle.alreadyProcessedSet.Add(obj)) { return; } IEnumerator objEnumerator = ((IEnumerable)obj).GetEnumerator(); while (objEnumerator.MoveNext()) { MergeDeepIntern(objEnumerator.Current, handle); } } else { MergeOrPersist(obj, handle); } }
protected void MergePhase2(Object objectToMerge, Object objectToDelete, MergeHandle mergeHandle, ICUDResult cudResult, ProceedWithMergeHook proceedHook, MergeFinishedCallback mergeFinishedCallback, bool addNewEntitiesToCache) { List <Object> unpersistedObjectsToDelete = new List <Object>(); RemoveUnpersistedDeletedObjectsFromCudResult(cudResult.AllChanges, cudResult.GetOriginalRefs(), unpersistedObjectsToDelete); if (objectToDelete != null) { IList <IObjRef> oriList = OriHelper.ExtractObjRefList(objectToDelete, mergeHandle); AppendDeleteContainers(objectToDelete, oriList, cudResult.AllChanges, cudResult.GetOriginalRefs(), unpersistedObjectsToDelete); } // Store the MergeFinishedCallback from this thread on the stack and set the property null (for following calls): if (GuiThreadHelper.IsInGuiThread()) { GuiThreadHelper.InvokeOutOfGui(delegate() { MergePhase3(objectToMerge, unpersistedObjectsToDelete, cudResult, proceedHook, mergeFinishedCallback, addNewEntitiesToCache); }); } else { MergePhase3(objectToMerge, unpersistedObjectsToDelete, cudResult, proceedHook, mergeFinishedCallback, addNewEntitiesToCache); } }
protected virtual IList <IUpdateItem> AddModification(Object obj, MergeHandle handle) { IList <IUpdateItem> modItemList = handle.objToModDict.Get(obj); if (modItemList == null) { modItemList = new List <IUpdateItem>(); handle.objToModDict.Put(obj, modItemList); } return(modItemList); }
protected virtual bool EqualsReferenceOrId(Object original, Object clone, MergeHandle handle, IEntityMetaData metaData) { if (original == null) { return(clone == null); } if (clone == null) { return(false); } PrimitiveMember keyMember = metaData.IdMember; return(Object.Equals(keyMember.GetValue(clone, true), keyMember.GetValue(original, true))); }
protected virtual void MergeOrPersist(Object obj, MergeHandle handle) { if (obj == null || !handle.alreadyProcessedSet.Add(obj)) { return; } if (obj is IDataObject) { IDataObject dataObject = (IDataObject)obj; if (!dataObject.HasPendingChanges) { return; } if (dataObject.ToBeDeleted) { handle.objToDeleteSet.Add(obj); return; } } IEntityMetaData metaData = ((IEntityMetaDataHolder)obj).Get__EntityMetaData(); metaData.PrePersist(obj); Object key = metaData.IdMember.GetValue(obj, false); if (key == null) { Persist(obj, handle); return; } if (handle.Cache == null) { throw new Exception("Object has been cloned somewhere"); } Object clone = handle.Cache.GetObject(metaData.EntityType, key); if (clone == null) { throw new OptimisticLockException(null, metaData.VersionMember != null ? metaData.VersionMember.GetValue(obj, false) : null, obj); } Merge(obj, clone, handle); }
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); } } }
public ICUDResult CreateCUDResult(MergeHandle mergeHandle) { ILinkedMap <Type, ICUDResultExtension> typeToCudResultExtension = extensions.GetExtensions(); foreach (Entry <Type, ICUDResultExtension> entry in typeToCudResultExtension) { entry.Value.Extend(mergeHandle); } IdentityLinkedMap <Object, IList <IUpdateItem> > objToModDict = mergeHandle.objToModDict; IdentityHashSet <Object> objToDeleteSet = mergeHandle.objToDeleteSet; HashMap <Type, IPrimitiveUpdateItem[]> entityTypeToFullPuis = new HashMap <Type, IPrimitiveUpdateItem[]>(); HashMap <Type, IRelationUpdateItem[]> entityTypeToFullRuis = new HashMap <Type, IRelationUpdateItem[]>(); List <IChangeContainer> allChanges = new List <IChangeContainer>(objToModDict.Count); List <Object> originalRefs = new List <Object>(objToModDict.Count); foreach (Object objToDelete in objToDeleteSet) { IObjRef ori = OriHelper.GetCreateObjRef(objToDelete, mergeHandle); DeleteContainer deleteContainer = new DeleteContainer(); deleteContainer.Reference = ori; allChanges.Add(deleteContainer); originalRefs.Add(objToDelete); } IEntityMetaDataProvider entityMetaDataProvider = this.EntityMetaDataProvider; foreach (Entry <Object, IList <IUpdateItem> > entry in objToModDict) { Object obj = entry.Key; IList <IUpdateItem> modItems = entry.Value; IEntityMetaData metaData = entityMetaDataProvider.GetMetaData(obj.GetType()); IPrimitiveUpdateItem[] fullPuis = GetEnsureFullPUIs(metaData, entityTypeToFullPuis); IRelationUpdateItem[] fullRuis = GetEnsureFullRUIs(metaData, entityTypeToFullRuis); int puiCount = 0, ruiCount = 0; for (int a = modItems.Count; a-- > 0;) { IUpdateItem modItem = modItems[a]; Member member = metaData.GetMemberByName(modItem.MemberName); if (modItem is IRelationUpdateItem) { fullRuis[metaData.GetIndexByRelation(member)] = (IRelationUpdateItem)modItem; ruiCount++; } else { fullPuis[metaData.GetIndexByPrimitive(member)] = (IPrimitiveUpdateItem)modItem; puiCount++; } } IRelationUpdateItem[] ruis = CompactRUIs(fullRuis, ruiCount); IPrimitiveUpdateItem[] puis = CompactPUIs(fullPuis, puiCount); IObjRef ori = OriHelper.GetCreateObjRef(obj, mergeHandle); originalRefs.Add(obj); if (ori is IDirectObjRef) { CreateContainer createContainer = new CreateContainer(); ((IDirectObjRef)ori).CreateContainerIndex = allChanges.Count; createContainer.Reference = ori; createContainer.Primitives = puis; createContainer.Relations = ruis; allChanges.Add(createContainer); } else { UpdateContainer updateContainer = new UpdateContainer(); updateContainer.Reference = ori; updateContainer.Primitives = puis; updateContainer.Relations = ruis; allChanges.Add(updateContainer); } } return(new CUDResult(allChanges, originalRefs)); }
protected virtual void AddOriModification(Object obj, String memberName, Object value, Object cloneValue, MergeHandle handle) { if (value is IList) { IList list = (IList)value; for (int a = 0, size = list.Count; a < size; a++) { Object objItem = list[a]; MergeOrPersist(objItem, handle); } } else if (value is IEnumerable) { IEnumerator objEnumerator = ((IEnumerable)value).GetEnumerator(); while (objEnumerator.MoveNext()) { Object objItem = objEnumerator.Current; MergeOrPersist(objItem, handle); } } else { MergeOrPersist(value, handle); } try { IList <IObjRef> oldOriList = OriHelper.ExtractObjRefList(cloneValue, handle, handle.oldOriList); IList <IObjRef> newOriList = OriHelper.ExtractObjRefList(value, handle, handle.newOriList); IRelationUpdateItem oriModItem = CreateRUI(memberName, oldOriList, newOriList); if (oriModItem == null) { return; } IList <IUpdateItem> modItemList = AddModification(obj, handle); modItemList.Add(oriModItem); } finally { handle.oldOriList.Clear(); handle.newOriList.Clear(); } }
protected virtual bool IsMemberModified(Object objValue, Object cloneValue, MergeHandle handle, IEntityMetaData metaData) { if (objValue == null) { return(cloneValue != null); } if (cloneValue == null) { MergeDeepIntern(objValue, handle); return(true); } if (objValue is IList) { IList objList = (IList)objValue; IList cloneList = (IList)cloneValue; bool memberModified = false; if (objList.Count != cloneList.Count) { memberModified = true; } for (int a = 0, size = objList.Count; a < size; a++) { Object objItem = objList[a]; if (cloneList.Count > a) { Object cloneItem = cloneList[a]; if (!EqualsReferenceOrId(objItem, cloneItem, handle, metaData)) { memberModified = true; } } MergeOrPersist(objItem, handle); } return(memberModified); } if (objValue is IEnumerable) { IEnumerator objEnumerator = ((IEnumerable)objValue).GetEnumerator(); IEnumerator cloneEnumerator = ((IEnumerable)cloneValue).GetEnumerator(); bool memberModified = false; while (objEnumerator.MoveNext()) { if (!cloneEnumerator.MoveNext()) { memberModified = true; } else { if (!EqualsReferenceOrId(objEnumerator.Current, cloneEnumerator.Current, handle, metaData)) { memberModified = true; } } MergeOrPersist(objEnumerator.Current, handle); } return(memberModified); } MergeOrPersist(objValue, handle); return(!EqualsReferenceOrId(objValue, cloneValue, handle, metaData)); }
public IList <IObjRef> ExtractObjRefList(Object objValue, MergeHandle mergeHandle, IList <IObjRef> targetOriList) { return(ExtractObjRefList(objValue, mergeHandle, null, null)); }
protected virtual void AddModification(Object obj, String memberName, Type targetValueType, Object value, Object cloneValue, MergeHandle handle) { //foreach (IMergeExtension mergeExtension in mergeExtensions) //{ // if (mergeExtension.HandlesType(targetValueType)) // { // value = mergeExtension.ExtractPrimitiveValueToMerge(value); // } //} PrimitiveUpdateItem primModItem = new PrimitiveUpdateItem(); primModItem.MemberName = memberName; primModItem.NewValue = value; IList <IUpdateItem> modItemList = AddModification(obj, handle); modItemList.Add(primModItem); }
protected bool ArePrimitivesEqual(IEntityMetaData metaData, PrimitiveMember primitiveMember, Object objValue, Object cloneValue, MergeHandle handle) { if (objValue != null && cloneValue != null) { if (objValue is Array && cloneValue is Array) { Array objArray = (Array)objValue; Array cloneArray = (Array)cloneValue; if (objArray.Length != cloneArray.Length) { return(false); } for (int b = objArray.Length; b-- > 0;) { Object objItem = objArray.GetValue(b); Object cloneItem = cloneArray.GetValue(b); if (!EqualsObjects(objItem, cloneItem)) { return(false); } } return(true); } else if (objValue is IList && cloneValue is IList) { IList objList = (IList)objValue; IList cloneList = (IList)cloneValue; if (objList.Count != cloneList.Count) { return(false); } for (int b = objList.Count; b-- > 0;) { Object objItem = objList[b]; Object cloneItem = cloneList[b]; if (!EqualsObjects(objItem, cloneItem)) { return(false); } } return(true); } else if (TypeInfoProvider.GetTypeInfo(objValue.GetType()).DoesImplement(typeof(ISet <>)) && TypeInfoProvider.GetTypeInfo(cloneValue.GetType()).DoesImplement(typeof(ISet <>))) { if (((ICollection)objValue).Count != ((ICollection)cloneValue).Count) { return(false); } MethodInfo setEqualsMethod = cloneValue.GetType().GetMethod("SetEquals"); return((bool)setEqualsMethod.Invoke(cloneValue, new Object[] { objValue })); } else if (objValue is ICollection && cloneValue is ICollection) { IEnumerator objIter = ((IEnumerable)objValue).GetEnumerator(); IEnumerator cloneIter = ((IEnumerable)cloneValue).GetEnumerator(); while (objIter.MoveNext()) { if (!cloneIter.MoveNext()) { return(false); } Object objItem = objIter.Current; Object cloneItem = cloneIter.Current; if (!EqualsObjects(objItem, cloneItem)) { return(false); } } if (cloneIter.MoveNext()) { return(false); } return(true); } else if (objValue is IEnumerable && cloneValue is IEnumerable) { IEnumerator objIter = ((IEnumerable)objValue).GetEnumerator(); IEnumerator cloneIter = ((IEnumerable)cloneValue).GetEnumerator(); while (objIter.MoveNext()) { if (!cloneIter.MoveNext()) { return(false); } Object objItem = objIter.Current; Object cloneItem = cloneIter.Current; if (!EqualsObjects(objItem, cloneItem)) { return(false); } } if (cloneIter.MoveNext()) { return(false); } return(true); } } return(EqualsObjects(objValue, cloneValue)); }
protected void MergePrimitivesFieldBased(IEntityMetaData metaData, Object obj, Object clone, MergeHandle handle) { foreach (PrimitiveMember primitiveMember in metaData.PrimitiveMembers) { if (!metaData.IsMergeRelevant(primitiveMember)) { continue; } Object objValue = primitiveMember.GetValue(obj, true); Object cloneValue = primitiveMember.GetValue(clone, true); if (!ArePrimitivesEqual(metaData, primitiveMember, objValue, cloneValue, handle)) { AddModification(obj, primitiveMember.Name, primitiveMember.ElementType, objValue, cloneValue, handle); } } }
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); } } } }
public IObjRef GetCreateObjRef(Object obj, MergeHandle mergeHandle) { if (obj == null) { return(null); } IObjRef ori = null; IDictionary <Object, IObjRef> objToOriDict = mergeHandle != null ? mergeHandle.objToOriDict : null; if (objToOriDict != null) { ori = DictionaryExtension.ValueOrDefault(objToOriDict, obj); } if (ori != null) { return(ori); } if (obj is IObjRef) { return((IObjRef)obj); } if (!(obj is IEntityMetaDataHolder)) { return(null); } IEntityMetaData metaData = ((IEntityMetaDataHolder)obj).Get__EntityMetaData(); Object keyValue; if (obj is AbstractCacheValue) { keyValue = ((AbstractCacheValue)obj).Id; } else { keyValue = metaData.IdMember.GetValue(obj, false); } if (keyValue == null || mergeHandle != null && mergeHandle.HandleExistingIdAsNewId) { IDirectObjRef dirOri = new DirectObjRef(metaData.EntityType, obj); if (keyValue != null) { dirOri.Id = keyValue; } ori = dirOri; } else { Object version; if (obj is AbstractCacheValue) { version = ((AbstractCacheValue)obj).Version; } else { Member versionMember = metaData.VersionMember; version = versionMember != null?versionMember.GetValue(obj, true) : null; } ori = ObjRefFactory.CreateObjRef(metaData.EntityType, ObjRef.PRIMARY_KEY_INDEX, keyValue, version); } if (objToOriDict != null) { objToOriDict.Add(obj, ori); IDictionary <IObjRef, Object> oriToObjDict = mergeHandle != null ? mergeHandle.oriToObjDict : null; if (oriToObjDict != null && !oriToObjDict.ContainsKey(ori)) { oriToObjDict.Add(ori, obj); } } return(ori); }
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)); }