带有 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();
到您的派生上下文构造函数。
仅此而已。一旦上下文订阅了这些事件,它就会在实体最初被跟踪或状态发生变化时收到通知。您只对查询具体化未触发的 Modified
和 Added
状态感兴趣(如果您不需要 Added
,则只需将其从 if
条件中排除)。然后使用 EF Core 元数据服务检查实体是否包含 DateTime LastModified
属性,如果是,只需使用当前 date/time.
更新它
通过查看 DbContext class 文档,您可以覆盖 SaveChanges
方法并在其中设置 LastUpdated
值,然后再继续 base.SaveChanges()
最后。
最后一块 - 在 SaveChanges
方法中,您可以使用 ChangeTracker 属性.
找到 modified/newly 添加的实体
我想在我的大部分表格上基本上都有一个 "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
AndStateChanged
events onChangeTracker
can be used to write logic that reacts to entities entering theDbContext
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();
到您的派生上下文构造函数。
仅此而已。一旦上下文订阅了这些事件,它就会在实体最初被跟踪或状态发生变化时收到通知。您只对查询具体化未触发的 Modified
和 Added
状态感兴趣(如果您不需要 Added
,则只需将其从 if
条件中排除)。然后使用 EF Core 元数据服务检查实体是否包含 DateTime LastModified
属性,如果是,只需使用当前 date/time.
通过查看 DbContext class 文档,您可以覆盖 SaveChanges
方法并在其中设置 LastUpdated
值,然后再继续 base.SaveChanges()
最后。
最后一块 - 在 SaveChanges
方法中,您可以使用 ChangeTracker 属性.