Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

EntityFramework Core: Get changes occured in entity and related data

I want to get changes occured in an entity and related datas attached to it.

I know how to get the property names that have changed in one entity:

 dbContext.Entry(entity).Properties.Where(x => x.IsModified).Select(x => x.Metadata.Name).ToList();

How to do the same for related data in navigation properties ?

like image 477
frank_lbt Avatar asked Oct 30 '18 12:10

frank_lbt


People also ask

How do I track changes in Entity Framework?

In Entity Framework, change tracking is enabled by default. You can also disable change tracking by setting the AutoDetectChangesEnabled property of DbContext to false. If this property is set to true then the Entity Framework maintains the state of entities.

How does EF core detect changes?

By default, EF Core creates a snapshot of every entity's property values when it is first tracked by a DbContext instance. The values stored in this snapshot are then compared against the current values of the entity in order to determine which property values have changed.

How do you get entities back from a query without getting tracked by the context?

No-Tracking query using AsNoTracking() extention method The AsNoTracking() extension method returns a new query and returned entities do not track by the context. It means that EF does not perform any additional task to store the retrieve entities for tracking.

What difference does AsNoTracking () make?

AsNoTracking(IQueryable)Returns a new query where the entities returned will not be cached in the DbContext or ObjectContext. This method works by calling the AsNoTracking method of the underlying query object.


1 Answers

Based on this article (Entity Change Tracking using DbContext in Entity Framework 6), you should override SaveChanges() method to track entity changes and its related entities.

public override int SaveChanges()
{
    return base.SaveChanges();
} 

Actually, You should change the above code to the following sample:

public override int SaveChanges()
{
    var modifiedEntities = ChangeTracker.Entries()
        .Where(p => p.State == EntityState.Modified).ToList();
    var now = DateTime.UtcNow;

    foreach (var change in modifiedEntities)
    {
        var entityName = change.Entity.GetType().Name;
        var primaryKey = GetPrimaryKeyValue(change);

        foreach(var prop in change.OriginalValues.PropertyNames)
        {
            var originalValue = change.OriginalValues[prop].ToString();
            var currentValue = change.CurrentValues[prop].ToString();
            if (originalValue != currentValue) //Only create a log if the value changes
            {
                //Create the Change Log
            }
        }
    }
    return base.SaveChanges();
}
like image 126
Siavash Avatar answered Sep 24 '22 16:09

Siavash