实体框架代码第一个DateTime字段在修改时更新。

问题描述 投票:7回答:3

我有以下实体。

public class User
{
    public int UserId { get; set; }
    public string UserName { get; set; }
    public string UserAddress { get; set; }
    public DateTime CreateDate { get; set; }
    public DateTime? UpdateDate { get; set; }
}

我怎么能让 UpdateDate 的领域 User 实体成为服务器 DateTime 的更新?也就是说,每当数据库中的一个实体被修改时,就会在更新后的 UpdateDate 字段更改为该确切的日期和时间,就像说 UpdateDate = new DateTime(Datetime.Now.Ticks)

c# entity-framework datetime ef-code-first ef-migrations
3个回答
14
投票

首先,考虑到 DateTimeOffset 是一个更好的选择,如果你要存储本地时间。 或者,你可以使用一个基于UTC的 DateTime但我将展示 DateTimeOffset 在本例中。 永远不要存储基于本地的 DateTime 为此,你会遇到时区和夏令时的问题。 另请参阅。 反对DateTime.Now的案例.

接下来,考虑一个通用的接口,你可以为你希望跟踪创建-更新值的实体使用。

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

将该接口和它的属性应用到你正在处理的实体上。

public class User : IDatedEntity
{
    // ...

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

现在在你的数据库上下文中,你可以将你的实体附加到 SavingChanges 事件,并应用所需的行为。

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();
        };
    }
}

注意最后对 DetectChanges这将确保新更新的日期值应用于所有修改的实体。


0
投票

只有在迁移时才能这样做。将UpdateDate属性的defaultSqlValue参数设置为 "GETDATE() "或 "GETUTCDATE()",当你修改或添加新实体时,你需要将其值设置为null。


0
投票

如果你使用的是.NET Core和Entity Framework Core,我发现最简单的方法是使用内置的 ChangeTracker 并订阅其事件 ChangeTracker_StateChanged 当一个实体改变状态时,它将会随时触发。

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;
            }
        }
    }

然后我在几个项目中使用这个BaseDbContext,这些项目的实体都扩展了一个 BaseEntity 附带 UpdatedDate 领域:

© www.soinside.com 2019 - 2024. All rights reserved.