The need for change tracking

You can only persist entity objects to the database efficiently if you know which data in the object was changed since it was retrieved from the database. This is especially true if the object holds references to associated entities.

For example, suppose an entity object Album has a property named Tracks, which is represented as a collection containing all tracks for that album (a one-to-may relation in the database). After an Album object has been retrieved from the database a user can change the tracks collection, for example by adding a track. If at a later stage the object must be persisted (saved) to the database and we do not know whether tracks have been added/removed, there is a lot of work to do: we must loop through all rows of the related table, and for each row:

  • Set foreign key of track row to null, if foreign key value is same a primary key of album, but is not contained in current tracks collection
  • Set foreign key in track row to primary key of album, if row is contained in current tracks collection

Not very efficient, since we have to loop through all rows of the associated table every time the parent is saved.

But also for properties containing a single value it is nice to know whether the value has changed, so that if the object is saved to the database we can generate an UPDATE statement with only those columns that need to be updated. Also, maybe we want to check if an entity is “dirty” (changed) before we decide to execute an update statement.

For this to work, we need some sort of property change notification mechanism in our entity objects.

Implementing property change notifications

.NET provides an interface for property change tracking: INotificationChanged. The MSDN documentation tells us:

The INotifyPropertyChanged interface is used to notify clients, typically binding clients, that a property value has changed.

For example, consider a Person object with a property called FirstName. To provide generic property-change notification, the Person type implements the INotifyPropertyChanged interface and raises a PropertyChanged event when FirstName is changed.

When implementing the INotifyPropertyChange interface, a property declaration can look like this:

public string PhoneNumber
{
    get { return this.phoneNumberValue; }

    set
    {
        if (value != this.phoneNumberValue)
        {
            this.phoneNumberValue = value;
            NotifyPropertyChanged("PhoneNumber");
        }
    }
}

Not very complex. But, by explicitly raising an PropertyChanged in every property setter, there will be considerable amount of “extra” code, compared to the minimal approach to writting getters/setters:

public string PhoneNumber
{
    get { return this.phoneNumberValue; }
    set { this.phoneNumberValue = value; }
}

So implementing INotifyPropertyChange causes my entity code to grow, while I was so proud of my compact entities!
It also means repetitive work when defining an entity: in every property the NotifyPropertyChanged must be called. This is less of a problem if code generation is used to generate entities, but still. I think generated code also should be as readable as possible, and using longer property setters does not really help with that.

AOP

So, is there a way to implement IPropertyChanged automatically with less code in the entity classes?

Yes, there is. Ayende Rahien list 7 Approaches for AOP in .Net in is blog post. AOP stands for Aspect-Oriented Programming: a technique that can be used to attach event handlers to properties of an object at runtime (amongst other things). Sounds good huh? But, every approach comes with a price: weight, bad performance or complex implementation.

AOP is a powerful technique when used with libraries Cecil Mono. But if you, like me, don’t want to use 3rd party libraries in your project, implementing AOP is not really an option. Unless of course you want to spend a considerable amount of time writing (very) complex code.

Claytons Interception

Luckily, there is yet an other way to monitor property changes: semi-automatic notifications, called Claytons Interception by John Rusk in his blog post . It is also the way Mindscape LightSpeed handles property change interception:

public string DisplayName
{
get { return _displayName; }
set { Set(ref _displayName, value, "DisplayName"); }
}

Basically, what happens here: we do not directly set a field value in the property setter, but call special method in the setter that does this for us. This Set() function sets the field value and raises the appropriate change event.

For this to work, the Set() function needs to know the name of the changed property, that’s why we pass in the property name as a String. Here you can see a disadvantage of this method: automatic refactoring won’t work. However, the example above is most basic implementation of this technique. John Rusk describes in his blog posts a more advanced variant, which does not need a string argument.

TrackedList<T>

After finding out how we can track changes in single values, it is time to figure out a way to track collections. I use a data structure for this purpose I call a TrackedList.

A TrackedList is a list that tracks all its insertions and removals. We can ask the list for example which items where added since instantiation. In DynamicModel, TrackedLists are used for one purpose: to track changes in the children collection of a parent entity. Example of a property declaration for tracks in the Album entity:

[HasMany("AlbumId")]
public TrackedList<Track> Tracks
  get { return _tracks; }
  set {  _tracks = _value; }
}

I was surprised to find that there aren’t many examples on the internet of collection data structures in C# that can tracks changes. I only found one blog post (from 2005!) on this subject by Robert McLaws: “Tracking Collection Changes: Introducing SmartList“.

There is much information about a closely related subject though: persistent data structures. But persistent collections feel unnecessary heavy for my needs: a persistent collections always preserves the previous version of itself when modified, whereas my TrackedList only remembers which elements were inserted/deleted, not when or in which order.

The declaration of my TrackedList:

public class TrackedList<T> : IList, IList<T>

Since my TrackedList inherits from List, instances behave similar to “normal” C# lists. The two most important “special” methods are:

  • public ICollection<T> GetRemovals()
  • public ICollection<T> GetInsertions()

These methods returns all elements that where inserted/removed since instantiation of the list. Tracking can be temporarily switched of, by setting the boolean property Tracking of the list to false.

The class hold two HashSets: one containing insertions, one containing deletions. Every time an item is added to the list (for example through the Add() or Insert() methods), the item is also added to the appropriate HashSet (same for removals).

So far, my TrackedList seems to be well suited for the job of holding child entities. But I’m not sure whether there are advantages (in this particular case) of using a more advanced data structure (e.g. a persistent collection) that I miss. Feel free to show you opinion in the comments.

Read more on change tracking:
Claytons Interception

2 Responses to “INotifyPropertyChanged and TrackedList

  1. Thanks for the link! FYI, .NET 4 has the built-in option “ObservableCollection”, which throws events as items go in and out of the list. The “Self-Tracking Entities” in Entity Framework 4 also have change-tracker object that can be used to manage changes to collections, much in the same way the SmartList or TrackedList do.

    HTH!

  2. admin says:

    Thanks for your comment Robert!
    I don’t use .NET 4 yet, but I will certainly look into the ObservableCollection.

Leave a Reply





Human Verification