So, we are porting an old wpf app into .net core wpf. As part of the effort we are also moving the data layer to EF.net core
.
entity.HasChangeTrackingStrategy(ChangeTrackingStrategy.ChangingAndChangedNotificationsWithOriginalValues);
On edit, the object gets updated, on Reload() it gets reverted from tracked original values. Object wise, the operations are ok, however, the wpf side of things is not working ok. It seems the ef.net core is a very maladjusted citizen of the wpf application, assuming its the sole beneficiary of INotifyPropertyChanged mechanism. Which is, of course, not true in the slightest for WPF.
dbContext.Entry(c).Reload();
. So question #1, is there a way to force ef.net to work with properties and not fields?INotifyPropertyChanged
seems to be flawed. If you invoke PropoertyChanged event on a property, without actually changing it, it will mark the entity as Modified
, even though it can easily compare original and current value. This prohibits us from manually raising property changed events to control WPF rendering. Not sure how to solve this, or if its even solvable because it only applies to this tracking strategy. I am open to any suggestion on how I can notify WPF elements without riling up ef.net.dbContext.Entry(entry).State
which exists outside of any WPF bindings within DataContext
hierarchy. It makes binding on state virtually impossible (for example to change the background of dirty entries or show Save button, etc). We "solved" it by inheriting all our entity classes from NotifySetterObject
base class which handles INotify*
implementation and also keeps [NotMapped] bool IsDirty
flag. Needless to say, I dislike this heavily, keeping two unlinked state flags sounds like an accident waiting to happen. I am wondering if you encountered similar problem and if you devised a better, more sane, solution. EF.net seems to have undergone a breaking change transformation from framework ef.net in terms of being only well suited for detached context scenarios (like asp.net). Are we wasting our time here trying to fit this shoe on wpf? Should we maybe focus on a different OR engine more suited to live contexts?
Before trying to address your questions, let me point out some things:
You are using EF Core 3.0, which currently is in preview (beta), so many things might not work as expected.
If by ef.net
you mean EF6, i.e. the old project you are porting was using EF6, it's not strongly necessary to switch to EF Core - EF6 is also getting .Net Core support - a preview version is available here.
Now regarding your concrete questions:
EF Core can use properties, field or both. This is configurable via fluent API at context, entity and property level. Just the EF Core 3.0 default has changed - you can see that in Breaking Changes - Backing fields are used by default. The link also shows how the get the desired behavior by using
.UsePropertyAccessMode(PropertyAccessMode.FieldDuringConstruction)
on model (all entities), entity (all entity properties) or property (specific entity property) builders.
Original values are recorded when the entity raises the
PropertyChanging
. Properties are marked as modified when the entity raises thePropertyChanged
event.
So it is by design, hence there is nothing you can do about it. But solving #1 eliminates the need of manually raising PropertyChanged
event, and the two-way binding seem to work flawlessly.
ChangeTracker
- Tracked
and StateChanged
, which (especially the second) can be used to provide state change notifications. But the actual mechanism for that is left for you. For instance, you can use EF Core 2.1+ entity constructor service injection feature to inject DbContext
into entity, which in turn can subscribe to StateChanged
event and raise PropertyChanged
for its own unmapped State
property etc.