我正在将一个旧项目移植到ASP.NET 5和Entity Framework 7.我已经使用数据库第一种方法(DNX scaffold)来创建模型。
旧项目基于实体框架4,审核跟踪是通过覆盖SaveChanges
的{{1}}方法实现的:
DbContext
我的问题是,如何在Entity Framework 7中实现这一点?我必须先采用代码方法吗?
答案 0 :(得分:5)
基本上你有两种方法可以达到这个目的:
使用ChangeTracker API(EF 6 +):
这是我们目前在EF 6中的方式,它仍然有效并适用于EF 7:
首先,您必须确保您的实体正在为审计字段实现公共接口:
public interface IAuditableEntity
{
int? CreatedById { get; set; }
DateTime Created { get; set; }
int? ModifiedById { get; set; }
DateTime Modified { get; set; }
}
然后,您可以覆盖SaveChanges并使用审计值更新每个公共字段:
public override int SaveChanges()
{
int? userId = null;
if (System.Web.HttpContext.Current != null)
userId = (from user in Users.Where(u => u.UserName == System.Web.HttpContext.Current.User.Identity.Name) select user.Id).SingleOrDefault();
var modifiedEntries = ChangeTracker.Entries<IAuditableEntity>()
.Where(e => e.State == EntityState.Added || e.State == EntityState.Modified);
foreach (EntityEntry<IAuditableEntity> entry in modifiedEntries)
{
entry.Entity.ModifiedById = UserId;
entry.Entity.Modified = DateTime.Now;
if (entry.State == EntityState.Added)
{
entry.Entity.CreatedById = UserId;
entry.Entity.Created = DateTime.Now;
}
}
return base.SaveChanges();
}
使用EF 7新的“暗影属性”功能:
Shadow properties是您的实体类中不存在的属性。这些属性的值和状态仅在Change Tracker中维护。
换句话说,审核列不会在您的实体上公开,与上面的实体相比,它们似乎是一个更好的选择。
要实现阴影属性,首先必须在实体上配置它们。例如,假设您有一个需要拥有一些审计列的User对象:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<User>().Property<int>("CreatedById");
modelBuilder.Entity<User>().Property<DateTime>("Created");
modelBuilder.Entity<User>().Property<int>("ModifiedById");
modelBuilder.Entity<User>().Property<DateTime>("Modified");
}
配置完成后,您现在可以在SaveChanges()覆盖上访问它们并相应地更新它们的值:
public override int SaveChanges()
{
int? userId = null;
if (System.Web.HttpContext.Current != null)
userId = (from user in Users.Where(u => u.UserName == System.Web.HttpContext.Current.User.Identity.Name) select user.Id).SingleOrDefault();
var modifiedBidEntries = ChangeTracker.Entries<User>()
.Where(e => e.State == EntityState.Added || e.State == EntityState.Modified);
foreach (EntityEntry<User> entry in modifiedBidEntries)
{
entry.Property("Modified").CurrentValue = DateTime.UtcNow;
entry.Property("ModifiedById").CurrentValue = userId;
if (entry.State == EntityState.Added)
{
entry.Property("Created").CurrentValue = DateTime.UtcNow;
entry.Property("CreatedById").CurrentValue = userId;
}
}
return base.SaveChanges();
}
最后的想法:
为了实现像审计列这样的东西,我将采用阴影属性方法,因为这些是交叉关注的问题,并不一定属于我的域对象,因此以这种方式实现它们将使我的域对象保持良好和干净。
答案 1 :(得分:0)
我参与了一个可能有用的图书馆。
查看Audit.EntityFramework库,它拦截SaveChanges()
并与EF Core版本兼容。