I am implementing the INotifyPropertyChanged
Interface on my EF POCOs.
I have a function to reset changes:
var entry = db.Entry(c);
entry.CurrentValues.SetValues(entry.OriginalValues);
But it doesn't call INotifyPropertyChanged
. It does not call the setter at all.
Maybe there is a better way to reset an entity?
I am implementing the INotifyPropertyChanged Interface on my EF POCOs.
That means that you're using entity classes as view models. From that design decision it presumably follows that, in order to prevent saving changes, entities must be reset when a user cancels editing.
But it doesn't call INotifyPropertyChanged.
You noticing that the setter isn't called probably means that UI elements also must be notified of this resetting.
Now you can do two things: fix this bypassing of the setter, or fix the design.
EF core bypasses the setter because by default it tries to use a backing field. It's easy to stop EF from doing this. You can either break the naming convention EF follows, or tell it not to look at it altogether. EF won't find the backing field in code like this:
private string _titleField;
public string Title
{
get { return _titleField; }
set
{
_titleField = value;
// notification code
}
}
But it's not obvious from the code itself why the field has such an odd name. It's easily forgotten.
If you want EF to use the setter it should be configured explicitly:
modelBuilder.Entity<Post>().Property(p => p.Title)
.UsePropertyAccessMode(PropertyAccessMode.PreferFieldDuringConstruction);
According to PropertyAccessMode Enum, PreferFieldDuringConstruction
means that
All accesses to the property when constructing new entity instances goes directly to the field (...). All other uses of the property will go through the property (...)
Also entry.CurrentValues.SetValues(entry.OriginalValues)
will use the setter.
It would be much better, IMO, to change the design. Use a view model class (with INotifyPropertyChanged
) in the UI that only transfers its changes to the underlying entity class when saving is confirmed. Now if the user cancels changes you just discard (or reset with notifications) the view model and you're done. It'll never be necessary to "reset an entity".