实体框架 7 审核日志 [英] Entity Framework 7 audit log

查看:24
本文介绍了实体框架 7 审核日志的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在将一个旧项目移植到 ASP.NET 5 和 Entity Framework 7.我使用了数据库优先方法(DNX 脚手架)来创建模型.

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.

旧项目基于Entity Framework 4,通过覆盖DbContextSaveChanges方法实现审计跟踪:

The old project is based on Entity Framework 4 and audit tracking is implemented by overriding the SaveChanges method of the DbContext:

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 中实现这一点?我是否必须采用代码优先的方法?

My question is, how can I implement this in Entity Framework 7? Do I have to take the code first approach?

推荐答案

基本上你有两种方法可以实现:

Basically you have two ways to achieve this:

使用 ChangeTracker API (EF 6+):

这是我们目前在 EF 6 中执行的方式,它仍然有效并且适用于 EF 7:

This is the way we currently do it in EF 6 and it is still valid and working for 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; }
}


然后您可以覆盖 SaveChanges 并使用审核值更新每个公共字段:


Then you can override SaveChanges and update each common field with audit values:

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 新的阴影属性"功能:

阴影属性是实体类中不存在的属性.这些属性的值和状态完全在 Change Tracker 中维护.

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.

换句话说,审计列不会在您的实体上公开,与上面必须将它们包含在您的实体中的选项相比,这似乎是一个更好的选择.

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.

要实现影子属性,首先必须在实体上配置它们.例如,假设您有一个需要有一些审计列的 User 对象:

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:

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() 覆盖访问它们并相应地更新它们的值:


Once configured, now you can access them on SaveChanges() override and update their values accordingly:

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


最后的想法:

为了实现诸如审计列之类的东西,我将采用 Shadow Properties 方法,因为这些是横切关注点,不一定属于我的域对象,因此以这种方式实现它们将使我的域对象保持整洁.

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.

这篇关于实体框架 7 审核日志的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆