首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Entity Framework 7审计日志

Entity Framework 7审计日志
EN

Stack Overflow用户
提问于 2016-01-04 00:07:20
回答 2查看 5K关注 0票数 6

我正在将一个旧项目移植到DNX5和Entity Framework7。我使用了数据库优先的方法( ASP.NET scaffold)来创建模型。

旧项目基于实体框架4,审计跟踪是通过覆盖DbContextSaveChanges方法来实现的

代码语言:javascript
复制
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 Framework7中实现它?我必须采取代码优先的方法吗?

EN

回答 2

Stack Overflow用户

发布于 2016-05-08 10:44:08

基本上,有两种方法可以实现这一点:

使用ChangeTracker接口的 (EF 6+):

这是我们目前在EF 6中使用的方法,并且在EF 7中仍然有效:

首先,您必须确保您的实体为审计字段实现了一个公共接口:

代码语言:javascript
复制
public interface IAuditableEntity 
{
    int? CreatedById { get; set; }

    DateTime Created { get; set; }

    int? ModifiedById { get; set; }

    DateTime Modified { get; set; }
}

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

代码语言:javascript
复制
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中维护。

换句话说,审计列不会暴露在你的实体上,这似乎是一个更好的选择,而不是上面的那个,你必须在你的实体上包括它们。

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

代码语言:javascript
复制
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()重写上访问它们,并相应地更新它们的值:

代码语言:javascript
复制
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();
}

的最终想法:

为了实现像审计列这样的东西,我将采用影子属性方法,因为这些是横切关注点,不一定属于我的域对象,所以以这种方式实现它们将保持域对象的整洁。

票数 5
EN

Stack Overflow用户

发布于 2017-10-12 12:47:33

我曾经在一个库上工作,这可能会有所帮助。

看看Audit.EntityFramework库,它拦截SaveChanges(),并与EF核心版本兼容。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/34578573

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档