带有 EF Core 2.1 和 Sql 服务器的时间戳?

TimeStamp with EF Core 2.1 and Sql Server?

我想在我的大部分表格上基本上都有一个 "Last Updated" 列,以便我可以快速检查它上次更新的时间。

现在我只是输入一个日期时间,每次我在 C# 代码中执行操作时,我都会保存新的 DateTime 以更新该字段。当然这会导致我忘记这样做。

我想要更自动化的东西。我真的不需要这个用于审计目的,所以它不需要太高级。

我试过了

builder.Property(x => x.RowVersion).IsRowVersion();

什么应该成为时间戳,但是当我在数据库中查看时,我看到 0x00000000000007D1 我认为它看起来更像日期时间。

编辑

 public class CompanyConfig : IEntityTypeConfiguration<Company>
    {
        public void Configure(EntityTypeBuilder<Company> builder)
        {
            builder.HasKey(x => x.Id);
            builder.Property(x => x.Id).ValueGeneratedOnAdd();
            builder.Property<DateTime>("LastUpdated");
        }
    }

EF Core 中的模式是将 "LastUpdated" 设为 Shadow Property,并在 SaveChanges() 期间更新它。

参见,例如:Implementing Common Audit Fields with EF Core’s Shadow Property

假设您已经为您想要的每个实体定义了影子 属性 LastModified,就像您的示例中那样

builder.Property<DateTime>("LastUpdated");

问题是如何自动更新它。

David 的回答中描述的技术已经过时。仍然可以覆盖 SaveChanges(和 SaveChangesAsync),但恕我直言,有更好的方法,如 所示。它是基于接口的方法,但可以很容易地针对阴影 属性(或任何 属性 - 使用的方法适用于阴影和显式属性)进行调整。

快速回顾:从 v2.1 开始,EF Core 提供 State change events:

New Tracked And StateChanged events on ChangeTracker can be used to write logic that reacts to entities entering the DbContext or changing their state.

以下是您如何使用它们。将以下内容添加到派生上下文 class:

void SubscribeStateChangeEvents()
{
    ChangeTracker.Tracked += OnEntityTracked;
    ChangeTracker.StateChanged += OnEntityStateChanged;
}

void OnEntityStateChanged(object sender, EntityStateChangedEventArgs e)
{
    ProcessLastModified(e.Entry);
}

void OnEntityTracked(object sender, EntityTrackedEventArgs e)
{
    if (!e.FromQuery)
        ProcessLastModified(e.Entry);
}

void ProcessLastModified(EntityEntry entry)
{
    if (entry.State == EntityState.Modified || entry.State == EntityState.Added)
    {
        var property = entry.Metadata.FindProperty("LastModified");
        if (property != null && property.ClrType == typeof(DateTime))
            entry.CurrentValues[property] = DateTime.UtcNow;
    }
}

并添加

SubscribeStateChangeEvents();

到您的派生上下文构造函数。

仅此而已。一旦上下文订阅了这些事件,它就会在实体最初被跟踪或状态发生变化时收到通知。您只对查询具体化未触发的 ModifiedAdded 状态感兴趣(如果您不需要 Added,则只需将其从 if 条件中排除)。然后使用 EF Core 元数据服务检查实体是否包含 DateTime LastModified 属性,如果是,只需使用当前 date/time.

更新它

通过查看 DbContext class 文档,您可以覆盖 SaveChanges 方法并在其中设置 LastUpdated 值,然后再继续 base.SaveChanges()最后。

最后一块 - 在 SaveChanges 方法中,您可以使用 ChangeTracker 属性.

找到 modified/newly 添加的实体