我有以下实体:
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)
答案 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
。