public virtual void EnsurePropertyIsLoaded(object obj, IPropertyMap propertyMap) { IObjectManager om = this.Context.ObjectManager; IPersistenceEngine pe = this.Context.PersistenceEngine; ObjectStatus objStatus; PropertyStatus propStatus; objStatus = om.GetObjectStatus(obj); if (objStatus != ObjectStatus.Deleted) { if (objStatus == ObjectStatus.NotLoaded) { pe.LoadObject(ref obj); if (pe == null) { throw new ObjectNotFoundException("Object not found!"); // do not localize } } propStatus = om.GetPropertyStatus(obj, propertyMap.Name); if (propStatus == PropertyStatus.NotLoaded) { pe.LoadProperty(obj, propertyMap.Name); } } else { //We really ought to throw an exception here... } }
public void EnsureLoaded() { if (MuteNotify) { return; } IContext ctx = interceptable.GetInterceptor().Context; IObjectManager om = ctx.ObjectManager; PropertyStatus propStatus = om.GetPropertyStatus(interceptable, propertyName); if (propStatus == PropertyStatus.NotLoaded) { ObjectStatus objStatus = om.GetObjectStatus(interceptable); if (!(objStatus == ObjectStatus.UpForCreation)) { bool stackMute = MuteNotify; MuteNotify = true; ctx.PersistenceEngine.LoadProperty(interceptable, propertyName); MuteNotify = stackMute; } } }
protected virtual void HandleOneOnePropertySet(object obj, IPropertyMap propertyMap, object value, object oldValue) { this.Context.LogManager.Info(this, "Managing inverse one-one property relationship synchronization", "Writing to object of type: " + obj.GetType().ToString() + ", Property: " + propertyMap.Name); // do not localize PropertyStatus propStatus; IPropertyMap invPropertyMap = propertyMap.GetInversePropertyMap(); if (invPropertyMap == null) { return; } IObjectManager om = this.Context.ObjectManager; if (value != null) { propStatus = om.GetPropertyStatus(value, invPropertyMap.Name); if (propStatus == PropertyStatus.NotLoaded) { AddAction(InverseActionType.Set, value, invPropertyMap.Name, obj, obj); } else { om.EnsurePropertyIsLoaded(value, invPropertyMap); om.SetPropertyValue(value, invPropertyMap.Name, obj); om.SetNullValueStatus(value, invPropertyMap.Name, false); om.SetUpdatedStatus(value, invPropertyMap.Name, true); } } if (oldValue != null) { propStatus = om.GetPropertyStatus(value, invPropertyMap.Name); if (propStatus == PropertyStatus.NotLoaded) { AddAction(InverseActionType.Set, value, invPropertyMap.Name, null, obj); } else { om.EnsurePropertyIsLoaded(oldValue, invPropertyMap); om.SetPropertyValue(oldValue, invPropertyMap.Name, null); om.SetNullValueStatus(oldValue, invPropertyMap.Name, false); om.SetUpdatedStatus(oldValue, invPropertyMap.Name, true); } } }
public void ValidateObject(object obj, IList exceptions) { IObjectManager om = this.Context.ObjectManager; IClassMap classMap = this.Context.DomainMap.MustGetClassMap(obj.GetType()); ValidationMode objValidationMode = GetValidationMode(classMap); if (objValidationMode != ValidationMode.Off) { CustomValidateObject(obj, classMap, exceptions); ObjectStatus objStatus = om.GetObjectStatus(obj); foreach (IPropertyMap propertyMap in classMap.GetAllPropertyMaps()) { ValidationMode validationMode = GetValidationMode(classMap, propertyMap); if (validationMode != ValidationMode.Off) { PropertyStatus propStatus = om.GetPropertyStatus(obj, propertyMap.Name); if (validationMode == ValidationMode.ValidateAll && objStatus != ObjectStatus.UpForCreation) { this.Context.ObjectManager.EnsurePropertyIsLoaded(obj, propertyMap); } if (objStatus == ObjectStatus.UpForCreation || propStatus != PropertyStatus.NotLoaded) { bool ok = false; if (validationMode == ValidationMode.Default || validationMode == ValidationMode.ValidateLoaded || validationMode == ValidationMode.ValidateAll) { ok = true; } else if (validationMode == ValidationMode.ValidateDirty) { if (propStatus == PropertyStatus.Dirty) { ok = true; } } if (ok) { DoValidateProperty(obj, propertyMap, exceptions); } } } } } }
public virtual void InvalidateProperty(object obj, IPropertyMap propertyMap) { IObjectManager om = this.Context.ObjectManager; IPersistenceEngine pe = this.Context.PersistenceEngine; ObjectStatus objStatus; PropertyStatus propStatus; objStatus = om.GetObjectStatus(obj); propStatus = om.GetPropertyStatus(obj, propertyMap.Name); if (propStatus == PropertyStatus.NotLoaded) { RemoveOriginalValues(obj, propertyMap.Name); //pe.LoadProperty(obj, propertyMap.Name); } }
public void ValidateObject(object obj, IList exceptions) { IObjectManager om = this.Context.ObjectManager; IClassMap classMap = this.Context.DomainMap.MustGetClassMap(obj.GetType()); CustomValidateObject(obj, classMap, exceptions); ObjectStatus objStatus = om.GetObjectStatus(obj); foreach (IPropertyMap propertyMap in classMap.GetAllPropertyMaps()) { PropertyStatus propStatus = om.GetPropertyStatus(obj, propertyMap.Name); if (objStatus == ObjectStatus.UpForCreation || propStatus != PropertyStatus.NotLoaded) { DoValidateProperty(obj, propertyMap, exceptions); } } }
public virtual void InvalidateProperty(object obj, IPropertyMap propertyMap, bool invalidateDirty) { if (propertyMap.IsIdentity) { throw new NPersistException("Identity properties can not be invalidated! Property: " + AssemblyManager.GetBaseType(obj).Name + "." + propertyMap.Name, obj, propertyMap.Name); } IObjectManager om = this.Context.ObjectManager; IPersistenceEngine pe = this.Context.PersistenceEngine; PropertyStatus propStatus; propStatus = om.GetPropertyStatus(obj, propertyMap.Name); if (!(propStatus == PropertyStatus.Dirty && invalidateDirty == false)) { RemoveOriginalValues(obj, propertyMap.Name); } }
protected virtual void HandleOneManyPropertySet(object obj, IPropertyMap propertyMap, object value, object oldValue) { this.Context.LogManager.Info(this, "Managing inverse one-many property relationship synchronization", "Writing to object of type: " + obj.GetType().ToString() + ", Property: " + propertyMap.Name); // do not localize PropertyStatus propStatus; IPropertyMap invPropertyMap = propertyMap.GetInversePropertyMap(); if (invPropertyMap == null) { return; } IObjectManager om = this.Context.ObjectManager; IList list; IInterceptableList mList; bool stackMute = false; if (value != null) { propStatus = om.GetPropertyStatus(value, invPropertyMap.Name); if (propStatus == PropertyStatus.NotLoaded) { AddAction(InverseActionType.Add, value, invPropertyMap.Name, obj, obj); } else { om.EnsurePropertyIsLoaded(value, invPropertyMap); list = (IList)om.GetPropertyValue(value, invPropertyMap.Name); mList = list as IInterceptableList; if (mList != null) { stackMute = mList.MuteNotify; mList.MuteNotify = true; } list.Add(obj); if (mList != null) { mList.MuteNotify = stackMute; } om.SetUpdatedStatus(value, invPropertyMap.Name, true); } } if (oldValue != null) { propStatus = om.GetPropertyStatus(oldValue, invPropertyMap.Name); if (propStatus == PropertyStatus.NotLoaded) { AddAction(InverseActionType.Remove, oldValue, invPropertyMap.Name, obj, obj); } else { om.EnsurePropertyIsLoaded(oldValue, invPropertyMap); list = (IList)om.GetPropertyValue(oldValue, invPropertyMap.Name); mList = list as IInterceptableList; if (mList != null) { stackMute = mList.MuteNotify; mList.MuteNotify = true; } list.Remove(obj); if (mList != null) { mList.MuteNotify = stackMute; } } } }
protected virtual void HandleManyManyPropertySet(object obj, IPropertyMap propertyMap, IList newList, IList oldList) { this.Context.LogManager.Info(this, "Managing inverse many-many property relationship synchronization", "Writing to object of type: " + obj.GetType().ToString() + ", Property: " + propertyMap.Name); // do not localize PropertyStatus propStatus; IPropertyMap invPropertyMap = propertyMap.GetInversePropertyMap(); if (invPropertyMap == null) { return; } ArrayList added = GetListDiff(oldList, newList); ArrayList removed = GetListDiff(newList, oldList); IObjectManager om = this.Context.ObjectManager; IList list; IInterceptableList mList; bool stackMute = false; object value; foreach (object iValue in added) { value = iValue; propStatus = om.GetPropertyStatus(value, invPropertyMap.Name); if (propStatus == PropertyStatus.NotLoaded) { value = iValue; AddAction(InverseActionType.Add, value, invPropertyMap.Name, obj, obj); } else { //we still ensure so that the object is also always loaded... om.EnsurePropertyIsLoaded(value, invPropertyMap); list = (IList)om.GetPropertyValue(value, invPropertyMap.Name); mList = list as IInterceptableList; if (mList != null) { stackMute = mList.MuteNotify; mList.MuteNotify = true; } list.Add(obj); if (mList != null) { mList.MuteNotify = stackMute; } om.SetUpdatedStatus(value, invPropertyMap.Name, true); } } foreach (object iValue in removed) { value = iValue; propStatus = om.GetPropertyStatus(value, invPropertyMap.Name); if (propStatus == PropertyStatus.NotLoaded) { value = iValue; AddAction(InverseActionType.Remove, value, invPropertyMap.Name, obj, obj); } else { //we still ensure so that the object is also always loaded... om.EnsurePropertyIsLoaded(value, invPropertyMap); list = (IList)om.GetPropertyValue(value, invPropertyMap.Name); mList = list as IInterceptableList; if (mList != null) { stackMute = mList.MuteNotify; mList.MuteNotify = true; } list.Remove(obj); if (mList != null) { mList.MuteNotify = stackMute; } om.SetUpdatedStatus(value, invPropertyMap.Name, true); } } }
private void RefreshProperty(IObjectManager om, object targetObject, IPropertyMap propertyMap, IPersistenceManager pm, RefreshBehaviorType refreshBehavior, object value, out bool doWrite, out bool doWriteOrg) { doWrite = false; doWriteOrg = false; PropertyStatus propStatus = om.GetPropertyStatus(targetObject, propertyMap.Name); IClassMap classMap = this.Context.DomainMap.MustGetClassMap(targetObject.GetType()); RefreshBehaviorType useRefreshBehavior = pm.GetRefreshBehavior(refreshBehavior, classMap, propertyMap); if (useRefreshBehavior == RefreshBehaviorType.OverwriteNotLoaded || useRefreshBehavior == RefreshBehaviorType.DefaultBehavior) { //Overwrite both value and original far all unloaded properties if (propStatus == PropertyStatus.NotLoaded) { doWrite = true; doWriteOrg = true; } } else if (useRefreshBehavior == RefreshBehaviorType.OverwriteLoaded) { //Overwrite original for all properties //Overwrite value for all clean or unloaded properties (but not for dirty or deleted properties) doWriteOrg = true; if (propStatus == PropertyStatus.Clean || propStatus == PropertyStatus.NotLoaded) doWrite = true; } else if (useRefreshBehavior == RefreshBehaviorType.ThrowConcurrencyException) { //Overwrite original for all properties unless the old originial value and the fresh value from the //database mismatch, in that case raise an exception //Overwrite value for all clean or unloaded properties (but not for dirty or deleted properties) if (propStatus == PropertyStatus.Clean || propStatus == PropertyStatus.NotLoaded || propStatus == PropertyStatus.Dirty) { if (!(propStatus == PropertyStatus.NotLoaded)) { object testValue = om.GetOriginalPropertyValue(targetObject,propertyMap.Name); object testValue2 = value; if (DBNull.Value.Equals(testValue)) { testValue = null; } if (DBNull.Value.Equals(testValue2)) { testValue2 = null; } if (testValue2 != testValue) { string cachedValue = "null"; string freshValue = "null"; try { if (testValue != null) cachedValue = testValue.ToString() ; } catch { ; } try { if (value != null) freshValue = value.ToString() ; } catch { ; } throw new RefreshException("A refresh concurrency exception occurred when refreshing a cached object of type " + targetObject.GetType().ToString() + " with fresh data from the data source. The data source row has been modified since the last time this version of the object was loaded, specifically the value for property " + propertyMap.Name + ". (this exception occurs because ThrowConcurrencyExceptions refresh behavior was selected). Cashed value: " + cachedValue + ", Fresh value: " + freshValue, cachedValue, freshValue, targetObject, propertyMap.Name); // do not localize } } if (!(propStatus == PropertyStatus.Dirty)) doWrite = true; } } else if (useRefreshBehavior == RefreshBehaviorType.OverwriteDirty) { //Overwrite original for all properties //Overwrite value for all clean, unloaded or dirty properties (but not for deleted properties) doWriteOrg = true; if (!(propStatus == PropertyStatus.Deleted)) doWrite = true; } else { throw new NPersistException("Unknown object refresh behavior specified!"); // do not localize } }
private void RefreshProperty(IObjectManager om, object targetObject, IPropertyMap propertyMap, IPersistenceManager pm, RefreshBehaviorType refreshBehavior, object value, out bool doWrite, out bool doWriteOrg) { doWrite = false; doWriteOrg = false; PropertyStatus propStatus = om.GetPropertyStatus(targetObject, propertyMap.Name); IClassMap classMap = this.Context.DomainMap.MustGetClassMap(targetObject.GetType()); RefreshBehaviorType useRefreshBehavior = pm.GetRefreshBehavior(refreshBehavior, classMap, propertyMap); if (useRefreshBehavior == RefreshBehaviorType.OverwriteNotLoaded || useRefreshBehavior == RefreshBehaviorType.DefaultBehavior) { //Overwrite both value and original far all unloaded properties if (propStatus == PropertyStatus.NotLoaded) { doWrite = true; doWriteOrg = true; } } else if (useRefreshBehavior == RefreshBehaviorType.OverwriteLoaded) { //Overwrite original for all properties //Overwrite value for all clean or unloaded properties (but not for dirty or deleted properties) doWriteOrg = true; if (propStatus == PropertyStatus.Clean || propStatus == PropertyStatus.NotLoaded) { doWrite = true; } } else if (useRefreshBehavior == RefreshBehaviorType.ThrowConcurrencyException) { //Overwrite original for all properties unless the old originial value and the fresh value from the //database mismatch, in that case raise an exception //Overwrite value for all clean or unloaded properties (but not for dirty or deleted properties) if (propStatus == PropertyStatus.Clean || propStatus == PropertyStatus.NotLoaded || propStatus == PropertyStatus.Dirty) { if (!(propStatus == PropertyStatus.NotLoaded)) { object testValue = om.GetOriginalPropertyValue(targetObject, propertyMap.Name); object testValue2 = value; if (DBNull.Value.Equals(testValue)) { testValue = null; } if (DBNull.Value.Equals(testValue2)) { testValue2 = null; } if (testValue2 != testValue) { string cachedValue = "null"; string freshValue = "null"; try { if (testValue != null) { cachedValue = testValue.ToString(); } } catch {; } try { if (value != null) { freshValue = value.ToString(); } } catch {; } throw new RefreshException("A refresh concurrency exception occurred when refreshing a cached object of type " + targetObject.GetType().ToString() + " with fresh data from the data source. The data source row has been modified since the last time this version of the object was loaded, specifically the value for property " + propertyMap.Name + ". (this exception occurs because ThrowConcurrencyExceptions refresh behavior was selected). Cashed value: " + cachedValue + ", Fresh value: " + freshValue, cachedValue, freshValue, targetObject, propertyMap.Name); // do not localize } } if (!(propStatus == PropertyStatus.Dirty)) { doWrite = true; } } } else if (useRefreshBehavior == RefreshBehaviorType.OverwriteDirty) { //Overwrite original for all properties //Overwrite value for all clean, unloaded or dirty properties (but not for deleted properties) doWriteOrg = true; if (!(propStatus == PropertyStatus.Deleted)) { doWrite = true; } } else { throw new NPersistException("Unknown object refresh behavior specified!"); // do not localize } }
//[DebuggerStepThrough()] protected virtual void DoNotifyPropertySet(object obj, string propertyName, ref object value, object oldValue, bool hasOldValue, ref bool cancel) { IContext ctx = this.Context; IObjectManager om = ctx.ObjectManager; IPersistenceEngine pe = ctx.PersistenceEngine; PropertyCancelEventArgs e; if (hasOldValue) { e = new PropertyCancelEventArgs(obj, propertyName, value, oldValue, this.Context.ObjectManager.GetNullValueStatus(obj, propertyName)); } else { e = new PropertyCancelEventArgs(obj, propertyName, value, this.Context.ObjectManager.GetPropertyValue(obj, propertyName), this.Context.ObjectManager.GetNullValueStatus(obj, propertyName)); } this.Context.EventManager.OnWritingProperty(this, e); if (e.Cancel) { cancel = true; return; } value = e.NewValue; IClassMap classMap = ctx.DomainMap.MustGetClassMap(obj.GetType()); IPropertyMap propertyMap; string prevId; string newId; propertyMap = classMap.MustGetPropertyMap(propertyName); if (propertyMap.ReferenceType != ReferenceType.None && value != null) { if (propertyMap.ReferenceType == ReferenceType.OneToMany || propertyMap.ReferenceType == ReferenceType.OneToOne) { //parent object IInterceptable ivalue = value as IInterceptable; if (ivalue == null) { throw new NPersistException(string.Format("Object is not a NPersist managed object, do not use 'new' on Entities. (Property='{0}', Owner={1})", propertyName, obj)); } else { if (ivalue.GetInterceptor().Context != this.Context) { throw new NPersistException(string.Format("Object does not belong to the same context object as the property owner. (Property='{0}', Owner={1})", propertyName, obj)); } ObjectStatus valueObjectStatus = om.GetObjectStatus(value); if (valueObjectStatus == ObjectStatus.UpForDeletion || valueObjectStatus == ObjectStatus.Deleted) { throw new DeletedObjectException(string.Format("Object has been deleted. (Object={0})", value), value); } } } else if (propertyMap.ReferenceType == ReferenceType.ManyToOne || propertyMap.ReferenceType == ReferenceType.ManyToMany) { IInterceptableList ivalue = value as IInterceptableList; if (ivalue == null) { throw new NPersistException(string.Format("List is not a NPersist managed list, do not use 'new' to initialize lists, NPersist does this for you. (Property='{0}', Owner={1})", propertyName, obj)); } else if (ivalue.Interceptable.GetInterceptor().Context != this.Context) { throw new NPersistException(string.Format("List does not belong to the same context object as the property owner. (Property='{0}', Owner={1})", propertyName, obj)); } } } if (propertyMap.IsReadOnly) { //Let read-only inverse properties through if (!(propertyMap.ReferenceType != ReferenceType.None && propertyMap.Inverse.Length > 0 && propertyMap.NoInverseManagement == false)) { //Special - if someone forgot to make their ManyOne read-only, //why bug them about it? (so don't add an "else" with an exception...) if (propertyMap.ReferenceType != ReferenceType.ManyToOne) { throw new ReadOnlyException("Property '" + classMap.Name + "." + propertyName + "' is read-only!"); // do not localize } } } PropertyStatus propStatus = PropertyStatus.Clean; ObjectStatus objStatus = om.GetObjectStatus(obj); bool hasPropertyStatus = false; if (objStatus == ObjectStatus.Deleted) { throw new DeletedObjectException("The object has been deleted!", obj, propertyName); // do not localize } else if (objStatus == ObjectStatus.UpForDeletion) { throw new DeletedObjectException("The object has been registered as up for deletion!", obj, propertyName); // do not localize } this.Context.ObjectCloner.EnsureIsClonedIfEditing(obj); if (objStatus == ObjectStatus.UpForCreation) { } else if (objStatus == ObjectStatus.Clean) { propStatus = om.GetPropertyStatus(obj, propertyName); if (propStatus == PropertyStatus.NotLoaded) { pe.LoadProperty(obj, propertyName); } if (!(hasOldValue)) { if (!(om.ComparePropertyValues(obj, propertyName, value, om.GetPropertyValue(obj, propertyName)))) { this.Context.UnitOfWork.RegisterDirty(obj); } } } else if (objStatus == ObjectStatus.NotLoaded) { propertyMap = this.Context.DomainMap.MustGetClassMap(obj.GetType()).MustGetPropertyMap(propertyName); if (!(propertyMap.IsIdentity)) { propStatus = this.Context.ObjectManager.GetPropertyStatus(obj, propertyName); hasPropertyStatus = true; //it would be sweet to be able to determine beforehand if this property would be part of the span //that is loaded with LoadObject and only call LoadObject if that is the case.... if (propStatus == PropertyStatus.NotLoaded) { hasPropertyStatus = false; //this.Context.PersistenceEngine.LoadObject(ref obj); this.Context.IdentityMap.LoadObject(ref obj, true); if (obj == null) { throw new ObjectNotFoundException("Object not found!"); // do not localize } } if (!hasPropertyStatus) { propStatus = om.GetPropertyStatus(obj, propertyName); } if (propStatus == PropertyStatus.NotLoaded) { pe.LoadProperty(obj, propertyName); } } if (!(hasOldValue)) { if (!(om.ComparePropertyValues(obj, propertyName, value, om.GetPropertyValue(obj, propertyName)))) { this.Context.UnitOfWork.RegisterDirty(obj); } } } else if (objStatus == ObjectStatus.Dirty) { propStatus = om.GetPropertyStatus(obj, propertyName); if (propStatus == PropertyStatus.NotLoaded) { pe.LoadProperty(obj, propertyName); } } if (propertyMap.IsIdentity) { prevId = om.GetObjectIdentity(obj); newId = om.GetObjectIdentity(obj, propertyMap, value); if (prevId != newId) { ctx.IdentityMap.UpdateIdentity(obj, prevId, newId); } } om.SetNullValueStatus(obj, propertyName, false); om.SetUpdatedStatus(obj, propertyName, true); if (hasOldValue) { ctx.InverseManager.NotifyPropertySet(obj, propertyName, value, oldValue); ctx.UnitOfWork.RegisterDirty(obj); } else { ctx.InverseManager.NotifyPropertySet(obj, propertyName, value); } }
protected virtual Hashtable GetConcernedTableMaps(object obj, int exceptionLimit, Hashtable tableMaps, IDomainMap dm, IObjectManager om, bool update) { if (obj == null) return null; ITableMap tableMap = null; IClassMap classMap = dm.MustGetClassMap(obj.GetType()); if (classMap.Table != "") { tableMap = classMap.GetTableMap(); if (tableMap != null) tableMaps[tableMap] = tableMap; foreach (IPropertyMap propertyMap in classMap.GetAllPropertyMaps()) { if (propertyMap.Table != "") { if (!(propertyMap.IsSlave || propertyMap.IsReadOnly)) { bool ok = true; if (update) { PropertyStatus propStatus = om.GetPropertyStatus(obj, propertyMap.Name); if (propStatus != PropertyStatus.Dirty) ok = false; } if (ok) { tableMap = propertyMap.GetTableMap(); if (tableMap != null) tableMaps[tableMap] = tableMap; } } } } } return tableMaps; }