protected override void VisitEntityRef(IEntityRef entityRef, Entity parent, MetaMember member) { if (member.IsComposition) { Entity child = null; if (entityRef == null) { // If the EntityRef hasn't been accessed before, it might // not be initialized yet. In this case we need to access // the property directly to force it to load. child = (Entity)member.GetValue(parent); } else { child = entityRef.Entity; } if (child != null) { bool lastIsChild = this._isChild; this._isChild = true; this.Visit(child); this._isChild = lastIsChild; } } }
/// <summary> /// When a complex property on this instance changes, this method performs /// the necessary attach/detach operations for the new instance. /// </summary> /// <param name="metaMember">The complex member.</param> private void AttachComplexObjectInstance(MetaMember metaMember) { // First check if the parent has an existing instance attached for this // property and detach if necessary. string memberName = metaMember.Member.Name; ComplexObject prevInstance = null; if (this.TrackedInstances.TryGetValue(memberName, out prevInstance)) { prevInstance.Detach(); this.TrackedInstances.Remove(memberName); } ComplexObject newInstance = (ComplexObject)metaMember.GetValue(this); if (newInstance != null) { // Attach to the new instance newInstance.Attach(this, memberName, this.OnDataMemberChanging, this.OnDataMemberChanged, this.OnMemberValidationChanged); this.TrackedInstances[memberName] = newInstance; // If the instance has validation errors, we need to sync them into our parent. This // needs to be done as a merge operation, since the parent may already have property // level errors for this member that must be retained. if (newInstance.HasValidationErrors) { foreach (ValidationResult error in ValidationUtilities.ApplyMemberPath(newInstance.ValidationErrors, memberName)) { this.ValidationResultCollection.Add(error); } } } }
/// <summary> /// Resolves the conflict by updating the entity's original state with the current store state. /// If the entity has a timestamp concurrency member, the current store timestamp will be copied /// to the entity instance. <see cref="Entity.EntityConflict"/> is also cleared on <see cref="CurrentEntity"/>. /// </summary> /// <exception cref="InvalidOperationException">Thrown if <see cref="Resolve"/> is called when <see cref="IsDeleted"/> /// is <c>true</c>.</exception> public void Resolve() { if (this.CurrentEntity.EntityConflict == null) { // the conflict has already been resolved return; } if (this.IsDeleted) { throw new InvalidOperationException(Resource.EntityConflict_CannotResolveDeleteConflict); } // update the entity's original state this.CurrentEntity.UpdateOriginalValues(this.StoreEntity); // if the entity has a concurrency timestamp member, we must sync that // timestamp value into the current entity MetaMember versionMember = this._currentEntity.MetaType.VersionMember; if (versionMember != null) { object storeValue = versionMember.GetValue(this._storeEntity); // since Timestamp values are readonly, we must use ApplyState to set the value this._currentEntity.ApplyState(new Dictionary <string, object> { { versionMember.Name, storeValue } }); } // clear the conflict now that it is resolved this.CurrentEntity.EntityConflict = null; }
/// <summary> /// Determines whether the specified property has changed value. /// </summary> /// <param name="o">The parent of the property.</param> /// <param name="originalValues">The original values for the modified parent instance.</param> /// <param name="member">The property to check.</param> /// <returns>True if the property has changed, false otherwise.</returns> internal static bool PropertyHasChanged(object o, IDictionary <string, object> originalValues, MetaMember member) { if (originalValues == null) { return(false); } object currentValue = member.GetValue(o); object originalValue; if (!originalValues.TryGetValue(member.Name, out originalValue)) { throw new InvalidOperationException( string.Format(CultureInfo.CurrentCulture, Resource.Entity_Property_NotChangeTracked, member.Name, o.GetType())); } if (!object.Equals(currentValue, originalValue)) { return(true); } return(false); }