我有以下实体。
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)
首先,考虑到 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
这将确保新更新的日期值应用于所有修改的实体。
只有在迁移时才能这样做。将UpdateDate属性的defaultSqlValue参数设置为 "GETDATE() "或 "GETUTCDATE()",当你修改或添加新实体时,你需要将其值设置为null。
如果你使用的是.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
领域: