Background: I have a wpf 4.5 application that is built with MVVM (MVVM-Light) and Enitity Framework 6 db first.
I have several viewmodels that have a list/details set up with a list of objects in a listbox and a details grid that displays and allows the user to edit the selected record of the listbox. I have a SAVE and UNDO button at the top of the grid that I want to "enable" when there are changes to the underlying model entity of the selected record.
I am able to do this but the performance of my current solution is terrible and I need a new strategy to detect changes in my model.
What I Have Now:
I have a CanSaveExecute method that is the CanExecute Callback of an ICommand Object. IN that method I query the EF dbContext ChangeTracker Entities to see if any objects of my desired type are present.
Try If _Selection IsNot Nothing AndAlso _Selection.HasErrors = False Then Return (From entry In Context.ChangeTracker.Entries(Of job)() Where entry.Entity.idJob = _Selection.idJob And entry.State = EntityState.Modified Select entry).Count Else Return False End If Catch ex As Exception Return False End Try
The problem is that this query of the change tracker entries is destroying the UI performance. It causes serious lag with user input.
Does someone have a better strategy for detecting changes in a CanExecute method with Entity Framework 6? Preferably without changing the T4 codee (but I have a feeling this is where I will end up).
Here is how my model is set up. EF6 generates a simple entity class for me that looks like this (I removed a lot of properties to keep it simple as an example) :
Imports System Imports System.Collections.Generic Partial Public Class job Public Property idJob As Integer Public Property idLinkedJob As Nullable(Of Integer) Public Property idStatus As Byte Public Property idEstimate As Nullable(Of Integer) Public Property chrTitle As String Public Overridable Property alerts As ICollection(Of alert) = New HashSet(Of alert) Public Overridable Property client As client End Class
I extend that class with another partial class to add datavalidation rules like this (again, simplified for example) :
Partial Public Class job Inherits ValidationBase #Region "PROPERTIES" Public Property HasChanges As Boolean = False #End Region #Region "CONSTRUCTORS" Public Sub New() ''default values Me.FTC_Type = 4 Me.dtCreated = Now Me.dtUpdated = Now 'HasChanges = False End Sub Public ReadOnly Property DisplayPath Get Return "W" + idJob.ToString + ": " + chrTitle + " - " + client.chrCompany End Get End Property #End Region #Region "VALIDATION FUNCTIONS" Public Overrides Function Validate(validationContext As ComponentModel.DataAnnotations.ValidationContext) As IEnumerable(Of ComponentModel.DataAnnotations.ValidationResult) Return MyBase.Validate(validationContext) PropertyValitaion(True) End Function Public Sub PropertyValitaion(bAllProperties As Boolean, Optional sProperty As String = "") 'initialize validation helper If bAllProperties OrElse sProperty = "chrTitle" Then If String.IsNullOrEmpty(chrTitle) Then AddError("chrTitle", "You must enter a Job Title") Else RemoveError("chrTitle") End If End If If bAllProperties OrElse sProperty = "idClient" Then If idClient < 1 Then AddError("idClient", "You must select a job client") Else RemoveError("idClient") End If End If If String.IsNullOrEmpty(sProperty) = False Then OnPropertyChanged(sProperty) End If End Sub #End Region End Class
So after fighting with it for a day I've decided that @Shoe is right. Its turned out to be too much work for this feature. I could never get a call to the change tracker to not cause UI lag.
I'm just not seeing any advantages to the changes MS has made to Entity Framework. The classes no longer support change tracking and querying if there are changes is many times slower than using dbcontext. I wish they had documented all these changes better so I wouldn't have wasted so much time trying to get this to work.
Btw, if I use a viewmodel and let's say I have product entity with sixty fields. How do the changes on those fields get propagated back to the model?