private void MergeListRefProperty(IObjectManager om, object obj, IClassMap classMap, IPropertyMap propertyMap, object existing, PropertyStatus propStatus, PropertyStatus extPropStatus, bool forOrgValue, MergeBehaviorType mergeBehavior) { IList list = ((IList) om.GetPropertyValue(obj, propertyMap.Name)); IList orgList = ((IList) om.GetPropertyValue(existing, propertyMap.Name)); MergeReferenceLists(list, orgList, om, obj, mergeBehavior, classMap, propertyMap, existing, propStatus, extPropStatus, forOrgValue); }
private void MergeReferenceLists(IList list, IList orgList, IObjectManager om, object obj, MergeBehaviorType mergeBehavior, IClassMap classMap, IPropertyMap propertyMap, object existing, PropertyStatus propStatus, PropertyStatus extPropStatus, bool forOrgValue) { IList objectsToRemove = new ArrayList(); IList objectsToAdd = new ArrayList(); IUnitOfWork uow = this.Context.UnitOfWork; foreach (object itemOrgObj in orgList) { string itemOrgObjId = om.GetObjectIdentity(itemOrgObj); bool found = false; foreach (object itemObj in list) { string itemObjId = om.GetObjectIdentity(itemObj); if (itemObjId == itemOrgObjId) { found = true; break; } } if (!found) objectsToRemove.Add(itemOrgObj); } foreach (object itemObj in list) { string itemObjId = om.GetObjectIdentity(itemObj); bool found = false; foreach (object itemOrgObj in orgList) { string itemOrgObjId = om.GetObjectIdentity(itemOrgObj); if (itemObjId == itemOrgObjId) { found = true; break; } } if (!found) { object itemOrgObj = this.Context.GetObjectById(itemObjId, obj.GetType()); objectsToAdd.Add(itemOrgObj); } } if (objectsToRemove.Count > 0 || objectsToAdd.Count > 0) { bool keepExisting = KeepExistingValue(list, orgList, mergeBehavior, classMap, propertyMap, existing, obj, propStatus, extPropStatus, forOrgValue); if (!keepExisting) { bool stackMute = false; IInterceptableList mList = orgList as IInterceptableList; if (mList != null) { stackMute = mList.MuteNotify; mList.MuteNotify = true; } foreach (object itemOrgObj in objectsToRemove) orgList.Remove(itemOrgObj); foreach (object itemOrgObj in objectsToAdd) orgList.Add(itemOrgObj); if (mList != null) { mList.MuteNotify = stackMute; } if (propStatus == PropertyStatus.Dirty) { uow.RegisterDirty(existing); om.SetUpdatedStatus(existing, propertyMap.Name, true); } } } }
private void MergePrimitivePropertyValues(object value, object extValue, PropertyStatus propStatus, PropertyStatus extPropStatus, IObjectManager om, object existing, IClassMap classMap, IPropertyMap propertyMap, object obj, bool forOrgValue, MergeBehaviorType mergeBehavior) { if (!value.Equals(extValue)) // May be to naive - possibly should use some advanced method like ComparePropertyValues.. { bool keepExisting = KeepExistingValue(value, extValue, mergeBehavior, classMap, propertyMap, existing, obj, propStatus, extPropStatus, forOrgValue); if (!keepExisting) { if (forOrgValue) { om.SetPropertyValue(existing, propertyMap.Name, value); om.SetNullValueStatus(existing, propertyMap.Name, om.GetNullValueStatus(obj, propertyMap.Name)); if (propStatus == PropertyStatus.Dirty) { this.Context.UnitOfWork.RegisterDirty(existing); om.SetUpdatedStatus(existing, propertyMap.Name, true); } } else { om.SetOriginalPropertyValue(existing, propertyMap.Name, value); } } } }
private bool KeepExistingValue(object value, object extValue, MergeBehaviorType mergeBehavior, IClassMap classMap, IPropertyMap propertyMap, object existing, object obj, PropertyStatus propStatus, PropertyStatus extPropStatus, bool forOrgValue) { bool keepExisting = false; MergeBehaviorType useMergeBehavior = GetMergeBehavior(mergeBehavior, classMap, propertyMap); if (useMergeBehavior == MergeBehaviorType.ThrowConcurrencyException) throw new MergeException("Merge Conflict!", extValue, value, existing, obj, propertyMap.Name, forOrgValue); //First try: Dirty wins.. if (propStatus == PropertyStatus.Dirty && extPropStatus == PropertyStatus.Dirty) { if (useMergeBehavior == MergeBehaviorType.DefaultBehavior) throw new BothDirtyMergeException("Unresovable Merge Conflict! Both values are dirty!", extValue, value, existing, obj, propertyMap.Name, forOrgValue); else if (useMergeBehavior == MergeBehaviorType.IgnoreConflictsUsingMergeValue) keepExisting = false; else if (useMergeBehavior == MergeBehaviorType.IgnoreConflictsUsingCashedValue) keepExisting = true; else throw new NPersistException("This should be unreachable code...if it is not, that means I made a mistake!" ); } else if (propStatus == PropertyStatus.Dirty) keepExisting = false; else if (extPropStatus == PropertyStatus.Dirty) keepExisting = true; else { //Second try: Clean wins if (propStatus == PropertyStatus.Clean && extPropStatus == PropertyStatus.Clean) { if (useMergeBehavior == MergeBehaviorType.DefaultBehavior) throw new BothCleanMergeException("Unresovable Merge Conflict! Both values are clean!", extValue, value, existing, obj, propertyMap.Name, forOrgValue); else if (useMergeBehavior == MergeBehaviorType.IgnoreConflictsUsingMergeValue) keepExisting = false; else if (useMergeBehavior == MergeBehaviorType.IgnoreConflictsUsingCashedValue) keepExisting = true; else throw new NPersistException("This should be unreachable code...if it is not, that means I made a mistake!" ); } else if (propStatus == PropertyStatus.Clean) keepExisting = false; else if (extPropStatus == PropertyStatus.Clean) keepExisting = true; else { if (extPropStatus == PropertyStatus.NotLoaded) keepExisting = false; if (extPropStatus == PropertyStatus.Deleted) keepExisting = true; else throw new NPersistException("This should be unreachable code...if it is not, that means I made a mistake!" ); } } return keepExisting; }
private void MergePrimitiveProperty(IObjectManager om, object obj, IClassMap classMap, IPropertyMap propertyMap, object existing, bool forOrgValue, PropertyStatus propStatus, PropertyStatus extPropStatus, MergeBehaviorType mergeBehavior) { if (forOrgValue) { object value = om.GetPropertyValue(obj, propertyMap.Name); object extValue = om.GetPropertyValue(existing, propertyMap.Name); MergePrimitivePropertyValues(value, extValue, propStatus, extPropStatus, om, existing, classMap, propertyMap, obj, forOrgValue, mergeBehavior); } else { object orgValue = om.GetOriginalPropertyValue(obj, propertyMap.Name); object extOrgValue = om.GetOriginalPropertyValue(existing, propertyMap.Name); MergePrimitivePropertyValues(orgValue, extOrgValue, propStatus, extPropStatus, om, existing, classMap, propertyMap, obj, forOrgValue, mergeBehavior); } }
public virtual void MergeObjects(object obj, object existing, MergeBehaviorType mergeBehavior) { //What about transfering object status ? ...and property updated status ? INullValueHelper nullValueHelper = obj as INullValueHelper; if (nullValueHelper == null) throw new MissingInterfaceException("Can't merge object of type " + obj.GetType().ToString() + " since it does not implement the interface Puzzle.NPersist.Interface.INullValueHelper!"); IOriginalValueHelper originalValueHelper = obj as IOriginalValueHelper; if (originalValueHelper == null) throw new MissingInterfaceException("Can't merge object of type " + obj.GetType().ToString() + " since it does not implement the interface Puzzle.NPersist.Interface.IOriginalValueHelper!"); IUpdatedPropertyTracker updatedPropertyTracker = obj as IUpdatedPropertyTracker; if (updatedPropertyTracker == null) throw new MissingInterfaceException("Can't merge object of type " + obj.GetType().ToString() + " since it does not implement the interface Puzzle.NPersist.Interface.IUpdatedPropertyTracker!"); IObjectManager om = this.Context.ObjectManager; IClassMap classMap = this.Context.DomainMap.MustGetClassMap(obj.GetType()); foreach (IPropertyMap propertyMap in classMap.GetAllPropertyMaps()) { PropertyStatus propStatus = om.GetPropertyStatus(obj, propertyMap.Name); PropertyStatus extPropStatus = om.GetPropertyStatus(existing, propertyMap.Name); if (propStatus == PropertyStatus.Clean || propStatus == PropertyStatus.Dirty) { if (propertyMap.ReferenceType == ReferenceType.None) { MergePrimitiveProperty(om, obj, classMap, propertyMap, existing, true, propStatus, extPropStatus, mergeBehavior); MergePrimitiveProperty(om, obj, classMap, propertyMap, existing, false, propStatus, extPropStatus, mergeBehavior); } else { if (propertyMap.IsCollection) { MergeListRefProperty(om, obj, classMap, propertyMap, existing, propStatus, extPropStatus, true, mergeBehavior); MergeListRefProperty(om, obj, classMap, propertyMap, existing, propStatus, extPropStatus, false, mergeBehavior); } else { MergeSingleRefProperty(om, obj, classMap, propertyMap, existing, true, propStatus, extPropStatus, mergeBehavior); MergeSingleRefProperty(om, obj, classMap, propertyMap, existing, false, propStatus, extPropStatus, mergeBehavior); } } } } }
public virtual MergeBehaviorType GetMergeBehavior(MergeBehaviorType mergeBehavior, IClassMap classMap, IPropertyMap propertyMap) { if (mergeBehavior == MergeBehaviorType.DefaultBehavior) { mergeBehavior = propertyMap.MergeBehavior; if (mergeBehavior == MergeBehaviorType.DefaultBehavior) { mergeBehavior = classMap.MergeBehavior; if (mergeBehavior == MergeBehaviorType.DefaultBehavior) { mergeBehavior = classMap.DomainMap.MergeBehavior; if (mergeBehavior == MergeBehaviorType.DefaultBehavior) { mergeBehavior = m_MergeBehavior; if (mergeBehavior == MergeBehaviorType.DefaultBehavior) { mergeBehavior = MergeBehaviorType.TryResolveConflicts; } } } } } return mergeBehavior; }
private void MergeSingleRefProperty(IObjectManager om, object obj, IClassMap classMap, IPropertyMap propertyMap, object existing, bool forOrgValue, PropertyStatus propStatus, PropertyStatus extPropStatus, MergeBehaviorType mergeBehavior) { string extOrgObjId; string refObjId; object extRefObj; object refObj; object extOrgObj; if (forOrgValue) { refObj = om.GetOriginalPropertyValue(obj, propertyMap.Name); extOrgObj = om.GetOriginalPropertyValue(existing, propertyMap.Name); } else { refObj = om.GetPropertyValue(obj, propertyMap.Name); extOrgObj = om.GetPropertyValue(existing, propertyMap.Name); } if (refObj != null && DBNull.Value.Equals(refObj) != true) { refObjId = om.GetObjectIdentity(refObj); extOrgObjId = ""; if (extOrgObj != null) extOrgObjId = om.GetObjectIdentity(extOrgObj); if (!refObjId.Equals(extOrgObjId)) { bool keepExisting = KeepExistingValue(refObj, extOrgObj, mergeBehavior, classMap, propertyMap, existing, obj, propStatus, extPropStatus, forOrgValue); if (keepExisting != true) { extRefObj = this.Context.GetObjectById(refObjId, refObj.GetType()); SetSingleRefPropetyValue(forOrgValue, om, existing, propertyMap, extRefObj, propStatus); } } } else { if (extOrgObj != null) { bool keepExisting = KeepExistingValue(refObj, extOrgObj, mergeBehavior, classMap, propertyMap, existing, obj, propStatus, extPropStatus, forOrgValue); if (keepExisting) { SetSingleRefPropetyValue(forOrgValue, om, existing, propertyMap, null, propStatus); } } } }
private void MergeSingleRefProperty(IObjectManager om, object obj, IClassMap classMap, IPropertyMap propertyMap, object existing, bool forOrgValue, PropertyStatus propStatus, PropertyStatus extPropStatus, MergeBehaviorType mergeBehavior) { string extOrgObjId; string refObjId; object extRefObj; object refObj; object extOrgObj; if (forOrgValue) { refObj = om.GetOriginalPropertyValue(obj, propertyMap.Name); extOrgObj = om.GetOriginalPropertyValue(existing, propertyMap.Name); } else { refObj = om.GetPropertyValue(obj, propertyMap.Name); extOrgObj = om.GetPropertyValue(existing, propertyMap.Name); } if (refObj != null && DBNull.Value.Equals(refObj) != true) { //hmmmm won't this fail if we have two objects of different classes but with the same id? //probably the type should be included (and preferably change to KeyStruct comparisons...) refObjId = om.GetObjectIdentity(refObj); extOrgObjId = ""; if (extOrgObj != null) extOrgObjId = om.GetObjectIdentity(extOrgObj); if (!refObjId.Equals(extOrgObjId)) { bool keepExisting = KeepExistingValue(refObj, extOrgObj, mergeBehavior, classMap, propertyMap, existing, obj, propStatus, extPropStatus, forOrgValue); if (keepExisting != true) { extRefObj = this.Context.GetObjectById(refObjId, refObj.GetType()); SetSingleRefPropetyValue(forOrgValue, om, existing, propertyMap, extRefObj, propStatus); } } } else { if (extOrgObj != null) { bool keepExisting = KeepExistingValue(refObj, extOrgObj, mergeBehavior, classMap, propertyMap, existing, obj, propStatus, extPropStatus, forOrgValue); if (keepExisting) { SetSingleRefPropetyValue(forOrgValue, om, existing, propertyMap, null, propStatus); } } } }