entity framework7审核日志
我正在将一个旧项目移植到ASP.NET 5和Entity Framework 7.我使用数据库第一种方法(DNX scaffold)来创建模型。
旧项目基于entity framework4,审计跟踪是通过覆盖DbContext
的SaveChanges
方法实现的:
public override int SaveChanges(System.Data.Objects.SaveOptions options) { 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(); foreach (ObjectStateEntry entry in ObjectStateManager.GetObjectStateEntries(EntityState.Added | EntityState.Modified)) { Type EntityType = entry.Entity.GetType(); PropertyInfo pCreated = EntityType.GetProperty("Created"); PropertyInfo pCreatedById = EntityType.GetProperty("CreatedById"); PropertyInfo pModified = EntityType.GetProperty("Modified"); PropertyInfo pModifiedById = EntityType.GetProperty("ModifiedById"); if (entry.State == EntityState.Added) { if (pCreated != null) pCreated.SetValue(entry.Entity, DateTime.Now, new object[0]); if (pCreatedById != null && UserId != null) pCreatedById.SetValue(entry.Entity, UserId, new object[0]); } if (pModified != null) pModified.SetValue(entry.Entity, DateTime.Now, new object[0]); if (pModifiedById != null && UserId != null) pModifiedById.SetValue(entry.Entity, UserId, new object[0]); } } return base.SaveChanges(options); }
我的问题是,我如何在Entity Framework 7中实现它? 我必须采用代码第一种方法吗?
基本上你有两种方法来实现这个目标:
使用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() .Where(e => e.State == EntityState.Added || e.State == EntityState.Modified); foreach (EntityEntry 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新的“阴影属性”function:
阴影属性是实体类中不存在的属性。 这些属性的值和状态仅在Change Tracker中维护。
换句话说,审核列不会在您的实体上公开,与上面的实体相比,它们似乎是一个更好的选择。
要实现阴影属性,首先必须在实体上配置它们。 比方说,你有一个需要有一些审计列的User对象:
protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity().Property("CreatedById"); modelBuilder.Entity().Property("Created"); modelBuilder.Entity().Property("ModifiedById"); modelBuilder.Entity().Property("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() .Where(e => e.State == EntityState.Added || e.State == EntityState.Modified); foreach (EntityEntry 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(); }
最后的想法:
为了实现像审计列这样的东西,我将采用Shadow Properties方法,因为这些是交叉关注的问题,并不一定属于我的域对象,因此以这种方式实现它们将使我的域对象保持良好和干净。
我在一个可能有帮助的图书馆工作过。
看看Audit.EntityFramework库,它拦截了SaveChanges()
并与EF Core版本兼容。