期待构建一个框架(没有任何存储库模式可直接与DbSets一起使用)以自动填充“创建的”和“最后修改的”,而不是通过代码库散布这些代码。
您能指出正确的方向吗?
过去,我尝试将这些填充到构造函数中,但这似乎 就像讨厌的代码一样,每次我们从数据库EF中提取邮件时 更改跟踪会将实体标记为已修改。
.ctor()
{
Created = DateTime.Now;
LastModified = DateTime.Now;
}
public interface IHasCreationLastModified
{
DateTime Created { get; set; }
DateTime? LastModified { get; set; }
}
public class Account : IEntity, IHasCreationLastModified
{
public long Id { get; set; }
public DateTime Created { get; set; }
public DateTime? LastModified { get; set; }
public virtual IdentityUser IdentityUser { get; set; }
}
答案 0 :(得分:10)
从v2.1开始,EF Core提供了State change events:
Tracked
上的新StateChanged
和ChangeTracker
事件可用于编写逻辑,以对进入DbContext
或更改其状态的实体做出反应。
您可以从DbContext
构造函数内部订阅这些事件
ChangeTracker.Tracked += OnEntityTracked;
ChangeTracker.StateChanged += OnEntityStateChanged;
执行以下操作:
void OnEntityTracked(object sender, EntityTrackedEventArgs e)
{
if (!e.FromQuery && e.Entry.State == EntityState.Added && e.Entry.Entity is IHasCreationLastModified entity)
entity.Created = DateTime.Now;
}
void OnEntityStateChanged(object sender, EntityStateChangedEventArgs e)
{
if (e.NewState == EntityState.Modified && e.Entry.Entity is IHasCreationLastModified entity)
entity.LastModified = DateTime.Now;
}
答案 1 :(得分:2)
一种可行的解决方案(我们目前正在使用的解决方案)是在DbContext中覆盖SaveChanges()
方法,并添加一些代码以遍历设置值的更改实体
public override int SaveChanges()
{
var changedEntriesCopy = ChangeTracker.Entries()
.Where(e => e.State == EntityState.Added ||
e.State == EntityState.Modified ||
e.State == EntityState.Deleted)
.ToList();
var saveTime = DateTime.Now;
foreach (var entityEntry in changedEntriesCopy)
{
if (entityEntry.Metadata.FindProperty("Created") != null && entityEntry.Property("Created").CurrentValue == null)
{
entityEntry.Property("Created").CurrentValue = saveTime;
}
if (entityEntry.Metadata.FindProperty("Updated") != null)
{
entityEntry.Property("Updated").CurrentValue = saveTime;
}
}
return base.SaveChanges();
}
我们的处境基本上与以下情况类似-在我们的处境中创建的内容可以为空,因此在创建新实体时,代码中的值在创建之前为null(使您易于检查是否曾经填充过Created)。
可能还有其他解决方案,但这是最容易设置的解决方案,并且对性能没有明显影响