internal void RevertEntityToUnmodified(BaseRepository repository) { if ((_entity is INotifyPropertyChanged) && ! _propertyChanged) { // Shortcut exit - if not INPC events were raised, nothing should be changed. return; } if ((_unmodifiedStructuralPropertyValues == null) || (_unmodifiedNavigationPropertyValues == null)) { // It's not possible to revert throw new InvalidOperationException("Can't Revert because the entity's unmodified state was not captured."); } // Restore the unmodified property values for (int i = 0; i < _unmodifiedNavigationPropertyValues.Length; ++i) { PropertyInfo property = _entityTypeInfo.NavigationProperties[i]; // Check each property value before setting it - only set properties that need to change object currentValue = property.GetValue(_entity, null); if (! Equals(currentValue, _unmodifiedNavigationPropertyValues[i])) { object revertToValue = _unmodifiedNavigationPropertyValues[i]; property.SetValue(_entity, revertToValue, null); repository.DataServiceContext.SetLink(_entity, property.Name, revertToValue); } } for (int i = 0; i < _unmodifiedStructuralPropertyValues.Length; ++i) { PropertyInfo property = _entityTypeInfo.StructuralProperties[i]; property.SetValue(_entity, _unmodifiedStructuralPropertyValues[i], null); } // Set the state to unmodified in the DataServiceContext repository.DataServiceContext.ChangeState(_entity, EntityStates.Unchanged); // Set link collections, if any, to unmodified foreach (var linkCollectionTracker in _linkCollectionTrackers) { if (linkCollectionTracker != null) { linkCollectionTracker.RevertLinksToUnmodified(); } } _propertyChanged = false; }
/// <summary> /// Determine if the object is changed; and set the DataServiceContext state accordingly. /// </summary> /// <param name="repository"></param> internal void ReportChanges(BaseRepository repository) { EntityDescriptor ed = repository.DataServiceContext.GetEntityDescriptor(_entity); Debug.Assert(ed != null, "No EntityDescriptor for " + _entity); if ((ed.State == EntityStates.Unchanged) || (ed.State == EntityStates.Modified)) { if (_propertyChanged || !(_entity is INotifyPropertyChanged)) { // Only run this block if there's a chance a property has changed, // and if changed values will affect whether the entity is saved. if (AreStructuralPropertiesUnmodified()) { // Record the entity as Unmodified if (ed.State != EntityStates.Unchanged) { repository.DataServiceContext.ChangeState(_entity, EntityStates.Unchanged); } } else if (ed.State == EntityStates.Unchanged) { // Record the entity as Modified repository.DataServiceContext.UpdateObject(_entity); } // Set links for navigation properties that have changed for (int i = 0; i < _unmodifiedNavigationPropertyValues.Length; ++i) { PropertyInfo property = _entityTypeInfo.NavigationProperties[i]; // Check each property value before setting it - only set properties that need to change object currentValue = property.GetValue(_entity, null); if (! Equals(currentValue, _unmodifiedNavigationPropertyValues[i])) { repository.DataServiceContext.SetLink(_entity, property.Name, currentValue); } } } } else if (ed.State == EntityStates.Added) { // Set links for all navigation properties foreach (PropertyInfo navProperty in _entityTypeInfo.NavigationProperties) { object currentValue = navProperty.GetValue(_entity, null); if (currentValue != null) { // This may be unecessary, but if currentValue is already being tracked it will return immediately. // This is necessary if _entity doesn't implement INotifyPropertyChanged, and currentValue is new. _oDataClient.AddEntityGraph(currentValue); repository.DataServiceContext.SetLink(_entity, navProperty.Name, currentValue); } } } // Delegate reporting of link collection changes foreach (var linkCollectionTracker in _linkCollectionTrackers) { if (linkCollectionTracker != null) { linkCollectionTracker.ReportChanges(repository.ODataClient); } } }