Can you ignore an object’s OnPropertyChanged while retrieving a list of objects from Entity Framework?

I have an object where I have a OnPropertyChanged method that recalculates other object properties if one of the properties (restricted to a few key properties) is changed. This recalculation has a bit of performance overhead which is usually fine as it’s not called often in the app.

However when I retreive a large colletion of the object from the DBContext, it is taking a long time as it’s calling the OnPropertyChanged method for each object and each property in that object.

Is there a way I can tell the object to not raise OnPropertyChaged if it’s being contructed by EF? The only way I can think of is to not set the handler in the object constructor and do it after it has loaded but this is not very practical.

        protected void OnPropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propertyName = "") => OnPropertyChanged(new PropertyChangedEventArgs(propertyName));

        public event PropertyChangedEventHandler PropertyChanged;
        public Container()
        {
            Notifications = new List<Notification>();
            IsClosed = false;
            PropertyChanged += Container_DemurrageArgsChanged;
            
            
        }

        void Container_DemurrageArgsChanged(object sender, PropertyChangedEventArgs e)
        {
            ///Recalculate the demurrge values if any of the below fields are updated.
            var DemurrageProperties = new List<string> { "DwellStart", "ContainerSize", "BonusDays", "GateOutTimeStamp", "FreeDays" ,"ChargeDemurrage","Holidays","DailyCharge"};
            if (DemurrageProperties.Contains(e.PropertyName)) UpdateDemurrageVals();

        }

Answer

An alternative, You can try to use the DBContext event ObjectContext.ObjectMaterialized Event

Occurs when a new entity object is created from data in the data source as part of a query or load operation.

ObjectContext.ObjectMaterialized += OnEntityMaterialized;

But you will need to mark the entity as loaded or materialized

For example

private void OnEntityMaterialized(object sender, ObjectMaterializedEventArgs e)    
{
    var entity = e.Entity as BaseEntitie;
    if (entity != null)
        entity.IsMaterialized = true;
}

And change OnPropertyChanged

protected void OnPropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propertyName = "")
{
    if (IsMaterialized)
    {
        OnPropertyChanged(new PropertyChangedEventArgs(propertyName));
    }
}

Attention Point for the new entities because the event will not be raised. One possible solution is to change the condition to IsMaterialized || Id == 0

Leave a Reply

Your email address will not be published. Required fields are marked *