ChangeTracker.StateChanged of DbContext gets triggered when calling .Entry()

asp.net-core c# ef-core-2.1 entity-framework-core

Question

I implemented similar solution on how we can modify created and updated date upon saving data through EF Core as what is suggested here Populate Created and LastModified automagically in EF Core.

void OnEntityStateChanged(object sender, EntityStateChangedEventArgs e)
{
    if (e.NewState == EntityState.Modified && e.Entry.Entity is IHasCreationLastModified entity)
        entity.LastModified = DateTime.Now;
}

At first I thought this will be triggered only when SaveChanges() is called. But apparently it is also called on Entry()

// Get entity
var student = _dbContext.Students.Find(studentId);

// Modify student object
student.Name = "New student name";

// Called Entry(), trigger ChangeTracker.StateChanged
var entry = _dbContext.Entry(student);

// Doesn't trigger ChangeTracker.StateChanged
_dbContext.SaveChanges();

I found that ChangeTracker.StateChanged is triggered when _dbContext.Entry(student) is called. Then it doesn't get triggered again when _dbContext.SaveChanges() is called. And it also passes the condition above if (e.NewState == EntityState.Modified && e.Entry.Entity is IHasCreationLastModified entity).

My assumption why it is not triggered again when SaveChanges() is called, because there is no new update to the entity after Entity() is called.

This results in the LastModified property being assigned when .Entry(student) is called, instead of when .SaveChanges() is called.

Is there a way to only update LastModified property once when SaveChanges is called on the scenario above?

1
0
3/20/2019 2:41:37 AM

Accepted Answer

I suggest that you could override you SaveChanges method in your dbContext. You could refer to below code that I usually use.

public class ForumContext : DbContext
{
    public ForumContext(DbContextOptions<ForumContext> options) : base(options)
    {

    }
    //other settings
    public override int SaveChanges(bool acceptAllChangesOnSuccess)
    {
        foreach (var entry in ChangeTracker.Entries())
        {
            switch (entry.State)
            {
                case EntityState.Added:
                    ((BaseEntity)entry.Entity).AddedDate = DateTime.Now;
                    ((BaseEntity)entry.Entity).LastModified = DateTime.Now;
                    break;

                case EntityState.Modified:
                    ((BaseEntity)entry.Entity).LastModified = DateTime.Now;
                    break;

                case EntityState.Deleted:
                    entry.State = EntityState.Modified;
                    entry.CurrentValues["IsDeleted"] = true;
                    break;
            }
        }
        return base.SaveChanges(acceptAllChangesOnSuccess);
    }
1
3/20/2019 6:52:19 AM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow