Using the Editable<T> for wrapping the repetitive code was a good idea. I would however change a few things.
- I'd named it
ChangeTrackeras it better describes its purpose. - I'd named the
Changedproperty toIsDirty.Changedsounds more like an event. - I'd named the
_getSourcefield_getSourceValue. - Since you are interested in equality and not sorting, you should use the
EqualityComparer<TValue>.Defaultinstead. - This type does not have to be disposable. There are no resources to be freed and just setting all properties to some values on dispose is meaningless.
private IEditable[] _fields;private IEditable[] Fields
Having both a private field and a property is unnecessary.
ContactModel2 has become much smaller but it's still to large. The entire database code shouldn't be there. It belongs to a different layer.
RecordEditable - Same as above, it should be a different abstraction layer - not a part of the model and it also does not have to be disposable because it does not free any resources.
You might consider making the properties of the Contact virtual and override them in a new derived type like class ContactWithChangeTracking : Contact. This way you could still use the same old type as before but with additional abilities.