Adds some methods to TracksChangesEntityBase to enable/disable change tracking and to reset the change tracking dictionaries, this is then used for DeepCloning so that change tracking is turned off for the cloning process.
This commit is contained in:
@@ -460,10 +460,14 @@ namespace Umbraco.Core.Models
|
||||
public override object DeepClone()
|
||||
{
|
||||
var clone = (Content)base.DeepClone();
|
||||
|
||||
//turn off change tracking
|
||||
clone.DisableChangeTracking();
|
||||
//need to manually clone this since it's not settable
|
||||
clone._contentType = (IContentType)ContentType.DeepClone();
|
||||
//this shouldn't really be needed since we're not tracking
|
||||
clone.ResetDirtyProperties(false);
|
||||
//re-enable tracking
|
||||
clone.EnableChangeTracking();
|
||||
|
||||
return clone;
|
||||
|
||||
|
||||
@@ -609,13 +609,18 @@ namespace Umbraco.Core.Models
|
||||
public override object DeepClone()
|
||||
{
|
||||
var clone = (ContentTypeBase)base.DeepClone();
|
||||
|
||||
//turn off change tracking
|
||||
clone.DisableChangeTracking();
|
||||
//need to manually wire up the event handlers for the property type collections - we've ensured
|
||||
// its ignored from the auto-clone process because its return values are unions, not raw and
|
||||
// we end up with duplicates, see: http://issues.umbraco.org/issue/U4-4842
|
||||
|
||||
clone._propertyTypes = (PropertyTypeCollection)_propertyTypes.DeepClone();
|
||||
clone._propertyTypes.CollectionChanged += clone.PropertyTypesChanged;
|
||||
//this shouldn't really be needed since we're not tracking
|
||||
clone.ResetDirtyProperties(false);
|
||||
//re-enable tracking
|
||||
clone.EnableChangeTracking();
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
@@ -255,11 +255,15 @@ namespace Umbraco.Core.Models
|
||||
public override object DeepClone()
|
||||
{
|
||||
var clone = (ContentTypeCompositionBase)base.DeepClone();
|
||||
|
||||
//turn off change tracking
|
||||
clone.DisableChangeTracking();
|
||||
//need to manually assign since this is an internal field and will not be automatically mapped
|
||||
clone.RemovedContentTypeKeyTracker = new List<int>();
|
||||
clone._contentTypeComposition = ContentTypeComposition.Select(x => (IContentTypeComposition)x.DeepClone()).ToList();
|
||||
//this shouldn't really be needed since we're not tracking
|
||||
clone.ResetDirtyProperties(false);
|
||||
//re-enable tracking
|
||||
clone.EnableChangeTracking();
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
@@ -236,9 +236,17 @@ namespace Umbraco.Core.Models.EntityBase
|
||||
//Memberwise clone on Entity will work since it doesn't have any deep elements
|
||||
// for any sub class this will work for standard properties as well that aren't complex object's themselves.
|
||||
var clone = (Entity)MemberwiseClone();
|
||||
//ensure the clone has it's own dictionaries
|
||||
clone.ResetChangeTrackingCollections();
|
||||
//turn off change tracking
|
||||
clone.DisableChangeTracking();
|
||||
//Automatically deep clone ref properties that are IDeepCloneable
|
||||
DeepCloneHelper.DeepCloneRefProperties(this, clone);
|
||||
//this shouldn't really be needed since we're not tracking
|
||||
clone.ResetDirtyProperties(false);
|
||||
//re-enable tracking
|
||||
clone.EnableChangeTracking();
|
||||
|
||||
return clone;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,9 @@ namespace Umbraco.Core.Models.EntityBase
|
||||
public virtual IEnumerable<string> GetDirtyProperties()
|
||||
{
|
||||
return _propertyChangedInfo.Where(x => x.Value).Select(x => x.Key);
|
||||
}
|
||||
}
|
||||
|
||||
private bool _changeTrackingEnabled = true;
|
||||
|
||||
/// <summary>
|
||||
/// Tracks the properties that have changed
|
||||
@@ -41,6 +43,9 @@ namespace Umbraco.Core.Models.EntityBase
|
||||
/// <param name="propertyInfo">The property info.</param>
|
||||
protected virtual void OnPropertyChanged(PropertyInfo propertyInfo)
|
||||
{
|
||||
//return if we're not tracking changes
|
||||
if (_changeTrackingEnabled == false) return;
|
||||
|
||||
_propertyChangedInfo[propertyInfo.Name] = true;
|
||||
|
||||
if (PropertyChanged != null)
|
||||
@@ -132,6 +137,22 @@ namespace Umbraco.Core.Models.EntityBase
|
||||
_propertyChangedInfo = new Dictionary<string, bool>();
|
||||
}
|
||||
|
||||
protected void ResetChangeTrackingCollections()
|
||||
{
|
||||
_propertyChangedInfo = new Dictionary<string, bool>();
|
||||
_lastPropertyChangedInfo = new Dictionary<string, bool>();
|
||||
}
|
||||
|
||||
protected void DisableChangeTracking()
|
||||
{
|
||||
_changeTrackingEnabled = false;
|
||||
}
|
||||
|
||||
protected void EnableChangeTracking()
|
||||
{
|
||||
_changeTrackingEnabled = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used by inheritors to set the value of properties, this will detect if the property value actually changed and if it did
|
||||
/// it will ensure that the property has a dirty flag set.
|
||||
@@ -150,6 +171,9 @@ namespace Umbraco.Core.Models.EntityBase
|
||||
var initVal = value;
|
||||
var newVal = setValue(value);
|
||||
|
||||
//don't track changes, just set the value (above)
|
||||
if (_changeTrackingEnabled == false) return false;
|
||||
|
||||
if (Equals(initVal, newVal) == false)
|
||||
{
|
||||
OnPropertyChanged(propertySelector);
|
||||
@@ -157,5 +181,7 @@ namespace Umbraco.Core.Models.EntityBase
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -113,12 +113,15 @@ namespace Umbraco.Core.Models
|
||||
public override object DeepClone()
|
||||
{
|
||||
var clone = (File)base.DeepClone();
|
||||
|
||||
//turn off change tracking
|
||||
clone.DisableChangeTracking();
|
||||
//need to manually assign since they are readonly properties
|
||||
clone._alias = Alias;
|
||||
clone._name = Name;
|
||||
|
||||
//this shouldn't really be needed since we're not tracking
|
||||
clone.ResetDirtyProperties(false);
|
||||
//re-enable tracking
|
||||
clone.EnableChangeTracking();
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
@@ -399,14 +399,17 @@ namespace Umbraco.Core.Models
|
||||
public override object DeepClone()
|
||||
{
|
||||
var clone = (Macro)base.DeepClone();
|
||||
|
||||
//turn off change tracking
|
||||
clone.DisableChangeTracking();
|
||||
clone._addedProperties = new List<string>();
|
||||
clone._removedProperties = new List<string>();
|
||||
clone._properties = (MacroPropertyCollection)Properties.DeepClone();
|
||||
//re-assign the event handler
|
||||
clone._properties.CollectionChanged += clone.PropertiesChanged;
|
||||
|
||||
//this shouldn't really be needed since we're not tracking
|
||||
clone.ResetDirtyProperties(false);
|
||||
//re-enable tracking
|
||||
clone.EnableChangeTracking();
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
@@ -617,10 +617,14 @@ namespace Umbraco.Core.Models
|
||||
public override object DeepClone()
|
||||
{
|
||||
var clone = (Member)base.DeepClone();
|
||||
|
||||
//turn off change tracking
|
||||
clone.DisableChangeTracking();
|
||||
//need to manually clone this since it's not settable
|
||||
clone._contentType = (IMemberType)ContentType.DeepClone();
|
||||
//this shouldn't really be needed since we're not tracking
|
||||
clone.ResetDirtyProperties(false);
|
||||
//re-enable tracking
|
||||
clone.EnableChangeTracking();
|
||||
|
||||
return clone;
|
||||
|
||||
|
||||
@@ -415,15 +415,18 @@ namespace Umbraco.Core.Models.Membership
|
||||
public override object DeepClone()
|
||||
{
|
||||
var clone = (User)base.DeepClone();
|
||||
|
||||
//turn off change tracking
|
||||
clone.DisableChangeTracking();
|
||||
//need to create new collections otherwise they'll get copied by ref
|
||||
clone._addedSections = new List<string>();
|
||||
clone._removedSections = new List<string>();
|
||||
clone._sectionCollection = new ObservableCollection<string>(_sectionCollection.ToList());
|
||||
//re-create the event handler
|
||||
clone._sectionCollection.CollectionChanged += clone.SectionCollectionChanged;
|
||||
|
||||
//this shouldn't really be needed since we're not tracking
|
||||
clone.ResetDirtyProperties(false);
|
||||
//re-enable tracking
|
||||
clone.EnableChangeTracking();
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
@@ -160,10 +160,14 @@ namespace Umbraco.Core.Models
|
||||
public override object DeepClone()
|
||||
{
|
||||
var clone = (Property)base.DeepClone();
|
||||
|
||||
//turn off change tracking
|
||||
clone.DisableChangeTracking();
|
||||
//need to manually assign since this is a readonly property
|
||||
clone._propertyType = (PropertyType)PropertyType.DeepClone();
|
||||
//this shouldn't really be needed since we're not tracking
|
||||
clone.ResetDirtyProperties(false);
|
||||
//re-enable tracking
|
||||
clone.EnableChangeTracking();
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
@@ -456,14 +456,17 @@ namespace Umbraco.Core.Models
|
||||
public override object DeepClone()
|
||||
{
|
||||
var clone = (PropertyType)base.DeepClone();
|
||||
|
||||
//turn off change tracking
|
||||
clone.DisableChangeTracking();
|
||||
//need to manually assign the Lazy value as it will not be automatically mapped
|
||||
if (PropertyGroupId != null)
|
||||
{
|
||||
clone._propertyGroupId = new Lazy<int>(() => PropertyGroupId.Value);
|
||||
}
|
||||
|
||||
//this shouldn't really be needed since we're not tracking
|
||||
clone.ResetDirtyProperties(false);
|
||||
//re-enable tracking
|
||||
clone.EnableChangeTracking();
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
@@ -193,12 +193,15 @@ namespace Umbraco.Core.Models
|
||||
public override object DeepClone()
|
||||
{
|
||||
var clone = (Template)base.DeepClone();
|
||||
|
||||
//turn off change tracking
|
||||
clone.DisableChangeTracking();
|
||||
//need to manually assign since they are readonly properties
|
||||
clone._alias = Alias;
|
||||
clone._name = Name;
|
||||
|
||||
//this shouldn't really be needed since we're not tracking
|
||||
clone.ResetDirtyProperties(false);
|
||||
//re-enable tracking
|
||||
clone.EnableChangeTracking();
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
@@ -288,7 +288,8 @@ namespace Umbraco.Core.Models
|
||||
public override object DeepClone()
|
||||
{
|
||||
var clone = (UmbracoEntity) base.DeepClone();
|
||||
|
||||
//turn off change tracking
|
||||
clone.DisableChangeTracking();
|
||||
//This ensures that any value in the dictionary that is deep cloneable is cloned too
|
||||
foreach (var key in clone.AdditionalData.Keys.ToArray())
|
||||
{
|
||||
@@ -298,7 +299,10 @@ namespace Umbraco.Core.Models
|
||||
clone.AdditionalData[key] = deepCloneable.DeepClone();
|
||||
}
|
||||
}
|
||||
|
||||
//this shouldn't really be needed since we're not tracking
|
||||
clone.ResetDirtyProperties(false);
|
||||
//re-enable tracking
|
||||
clone.EnableChangeTracking();
|
||||
return clone;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user