8

The title is quite self-explanatory. Is there a built-in mechanism to support Created and Edited timestamps on records in a code-first database in Entity Framework Core?

Something like :created_at and :updated_at in Ruby on Rails migrations. I could not find any documentation concerning this. If no out-of-the-box mechanism is present, is there a best practice how to implement those columns?

lss
  • 1,235
  • 3
  • 15
  • 24

1 Answers1

4

The non EF Core solutions don't apply to EF Core without some amount of rework. I wanted to allow certain entities to have CreatedAt and LastModified timestamps that updated in a reasonably automated way. This is what I ended up doing.

  1. Defined an interface - ITimeStampedModel that my models could inherit from that required them to have the timestamps I wanted:

    public interface ITimeStampedModel
    {
        DateTime CreatedAt {get; set;}
        DateTime LastModified {get; set;}
    }
    
  2. Override SaveChanges on my DbContext to look for new or modified models, and update their timestamps appropriately:

    public override int SaveChanges()
    {
        var newEntities = this.ChangeTracker.Entries()
            .Where(
                x => x.State == EntityState.Added &&
                x.Entity != null &&
                x.Entity as ITimeStampedModel != null
                )
            .Select(x => x.Entity as ITimeStampedModel);
    
        var modifiedEntities = this.ChangeTracker.Entries() 
            .Where(
                x => x.State == EntityState.Modified &&
                x.Entity != null &&
                x.Entity as ITimeStampedModel != null
                )
            .Select(x => x.Entity as ITimeStampedModel);
    
        foreach (var newEntity in newEntities)
        {
            newEntity.CreatedAt = DateTime.UtcNow;
            newEntity.LastModified = DateTime.UtcNow;
        }
    
        foreach (var modifiedEntity in modifiedEntities)
        {
            modifiedEntity.LastModified = DateTime.UtcNow;
        }
    
        return base.SaveChanges();
    }
    

Anyone have a better solution?

Dbl
  • 5,634
  • 3
  • 41
  • 66
mattnedrich
  • 7,577
  • 9
  • 39
  • 45
  • I'd recommend to look for a way to update to set the time in the database instead of in the code. If the update to the database is done in batches or if the query takes a long time, the time won't be accurate. I'd say an entry's modified date should be set when it enters the database. – S. ten Brinke Nov 28 '18 at 13:30
  • 1
    @S.tenBrinke of course that would be better, but I wasn't able to find any easy-to-use and manage way of doing that alongside EF Core. It could perhaps he done with DB triggers, but then you would need to manage the triggers for each table (doesn't seem to scale very well). If you have any ideas please share them. – mattnedrich Nov 29 '18 at 14:35