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

时间:2014-07-05 22:00:15

标签: c# entity-framework datetime ef-code-first ef-migrations

我有以下实体:

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)

3 个答案:

答案 0 :(得分:12)

首先,如果您要存储当地时间,请考虑DateTimeOffset是更好的选择。或者,您可以使用基于UTC的DateTime,但我会在此示例中显示DateTimeOffset。切勿为此目的存储基于本地的DateTime,因为您将遇到时区和夏令时问题。另见:The Case Against 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的最终调用,这将确保将新更新的日期值应用于所有已修改的实体。

答案 1 :(得分:0)

您只能通过迁移执行此操作。将UpdateDate属性的defaultSqlValue参数设置为&#34; GETDATE()&#34;或&#34; GETUTCDATE()&#34;当您修改或添加新实体时,您需要将其值设置为null。

答案 2 :(得分: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

相关问题