简体   繁体   English

实体框架7审核日志

[英]Entity Framework 7 audit log

I am porting an old project over to ASP.NET 5 and Entity Framework 7. I have used the database first approach (DNX scaffold) to create the model. 我正在将一个旧项目移植到ASP.NET 5和Entity Framework 7.我已经使用数据库第一种方法(DNX scaffold)来创建模型。

The old project is based on Entity Framework 4 and audit tracking is implemented by overriding the SaveChanges method of the DbContext : 旧项目基于实体框架4,审计跟踪是通过覆盖DbContextSaveChanges方法实现的:

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);
}

My question is, how can I implement this in Entity Framework 7? 我的问题是,我如何在Entity Framework 7中实现这一点? Do I have to take the code first approach? 我必须先采用代码方法吗?

Basically you have two ways to achieve this: 基本上你有两种方法来实现这个目标:

Using ChangeTracker API (EF 6+): 使用ChangeTracker API(EF 6+):

This is the way we currently do it in EF 6 and it is still valid and working for EF 7: 这是我们目前在EF 6中的方式,它仍然有效并适用于EF 7:

First you have to make sure your entities are implementing a common interface for audit fields: 首先,您必须确保您的实体正在为审计字段实现通用接口:

public interface IAuditableEntity 
{
    int? CreatedById { get; set; }

    DateTime Created { get; set; }

    int? ModifiedById { get; set; }

    DateTime Modified { get; set; }
}


Then you can override SaveChanges and update each common field with audit values: 然后,您可以覆盖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();
}


Using EF 7 new "Shadow Properties" Feature: 使用EF 7新的“阴影属性”功能:

Shadow properties are properties that do not exist in your entity class. 阴影属性是实体类中不存在的属性。 The value and state of these properties is maintained purely in the Change Tracker. 这些属性的值和状态仅在Change Tracker中维护。

In other words, the audit columns will not be exposed on your entities which seems to be a better option compare to the one above where you have to include them on your entities. 换句话说,审核列不会在您的实体上公开,与上面的实体相比,它们似乎是一个更好的选择。

To implement shadow properties, first you have to configure them on your entities. 要实现阴影属性,首先必须在实体上配置它们。 Let's say for example you have a User object that needs to have some audit columns: 比方说,您有一个需要拥有一些审计列的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");
}


Once configured, now you can access them on SaveChanges() override and update their values accordingly: 配置完成后,您现在可以在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();
}


Final Thoughts: 最后的想法:

For implementing something like audit columns, I'll take the Shadow Properties approach since these are cross cutting concerns and do not necessarily belong to my domain objects so having them implemented this way will keep my domain objects nice and clean. 为了实现像审计列这样的东西,我将采用阴影属性方法,因为这些是交叉关注的问题,并不一定属于我的域对象,因此以这种方式实现它们将使我的域对象保持良好和干净。

I've worked on a library that might help. 我在一个可能有帮助的图书馆工作过。

Take a look at Audit.EntityFramework library, it intercepts SaveChanges() and is compatible with EF Core versions. 看一下Audit.EntityFramework库,它拦截了SaveChanges()并与EF Core版本兼容。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM