Entity Framework Code First DateTime field update on modification

前端 未结 3 2078
夕颜
夕颜 2020-12-30 14:00

I have the following entity:

public class User
{
    public int UserId { get; set; }
    public string UserName { get;         


        
相关标签:
3条回答
  • 2020-12-30 14:34

    You can do this only with migrations. Set defaultSqlValue parameter for UpdateDate property to "GETDATE()" or "GETUTCDATE()" and when you modify or add new entity you would need to set its value to null.

    0 讨论(0)
  • 2020-12-30 14:35

    If you're using .NET Core and Entity Framework Core the easiest way I found to this is to use the built-in ChangeTracker on the database context and subscribe to its event ChangeTracker_StateChanged which will trigger any time an Entity changes state. I implemented it like this:

    public abstract class BaseDbContext<T> : DbContext where T : DbContext
        {
            public BaseDbContext(DbContextOptions<T> options) : base(options)
            {
                this.ChangeTracker.StateChanged += ChangeTracker_StateChanged;
            }
    
            private void ChangeTracker_StateChanged(object sender, EntityStateChangedEventArgs e)
            {
                if (e.NewState == EntityState.Added || e.NewState == EntityState.Modified)
                {
                    var entity = (BaseEntity)e.Entry.Entity;
                    entity.UpdatedDate = DateTime.UtcNow;
                }
            }
        }
    

    I then use this BaseDbContext across several projects all of whose entities extend a BaseEntity with an UpdatedDate field.

    0 讨论(0)
  • 2020-12-30 14:40

    First, consider that DateTimeOffset is a better choice if you are going to be storing local times. Alternatively, you could use a UTC-based DateTime, but I will show DateTimeOffset in this example. Never store a local-based DateTime for this purpose, as you will have issues with time zones and daylight saving time. See also: The Case Against DateTime.Now.

    Next, consider a common interface that you can use for entities that you wish to track created/updated values.

    public interface IDatedEntity
    {
        DateTimeOffset Created { get; set; }
        DateTimeOffset Updated { get; set; }
    }
    

    Apply that interface and its properties to the entities you are working with.

    public class User : IDatedEntity
    {
        // ...
    
        public DateTimeOffset Created { get; set; }
        public DateTimeOffset Updated { get; set; }
    }
    

    Now in your database context, you can attach to the SavingChanges event and apply the desired behavior:

    public class MyContext : DbContext
    {
        public DbSet<User> Users { get; set; }
    
        public MyContext()
        {
            var objectContext = ((IObjectContextAdapter)this).ObjectContext;
            objectContext.SavingChanges += (sender, args) =>
            {
                var now = DateTimeOffset.Now;
                foreach (var entry in this.ChangeTracker.Entries<IDatedEntity>())
                {
                    var entity = entry.Entity;
                    switch (entry.State)
                    {
                        case EntityState.Added:
                            entity.Created = now;
                            entity.Updated = now;
                            break;
                        case EntityState.Modified:
                            entity.Updated = now;
                            break;
                    }
                }
                this.ChangeTracker.DetectChanges();
            };
        }
    }
    

    Note the final call to DetectChanges, which will ensure that the new updated date values are applied to all modified entities.

    0 讨论(0)
提交回复
热议问题