实体框架6:审计/跟踪变更

Pie*_*rto 47 c# audit entity-framework audit-trail entity-framework-6

我在C#中有我的核心项目.

我在一个数据库上工作,其中一些表有"user_mod"和"date_mod"列用于签名谁和什么时候做了一些mods和"data_new"和"user_new"相同.

我的问题:有没有办法集中这个并自动插入这些数据,我在哪里创建实例dbContext

如果没有,我将使用审计跟踪工具.我见过其中的一些,但是有一个问题:所有这些,需要我的模型中的一些代码.但是我不想在我的模型中写,因为如果我必须改变它,我将失去mod.是否可以在不写入模型文件的情况下使用EF6的审计跟踪?怎么样?

编辑:

我试图覆盖saveChanges.

public partial class PieEntities : DbContext
{
    public override int SaveChanges(System.Data.Objects.SaveOptions options)
    {
        var timestamp = DateTime.Now;

        EntityState es = EntityState.Added;
        ObjectStateManager o = new ObjectStateManager();

        foreach (ObjectStateEntry entry in o.GetObjectStateEntries(EntityState.Added ))  {
            if (entry.Entity.GetType() == typeof(TabImpianti)) {
                TabImpianti impianto = entry.Entity as TabImpianti;
                impianto.DATA_INS = timestamp;
                impianto.DATA_MOD = timestamp;
                string u = mdlImpostazioni.p.UserName;
                impianto.USER_INS = u;
                impianto.USER_MOD = u;
            }
        }
        return base.SaveChanges(options);
    }
}
Run Code Online (Sandbox Code Playgroud)

更新:我在这里总结了解决方案.

Ala*_*oud 70

如果使用EF6的DbContext你可以用ChangeTrackerSaveChanges重写找到自定义类型的添加/修改的实体,例如IAuditedEntity.

public interface IAuditedEntity {
  string CreatedBy { get; set; }
  DateTime CreatedAt { get; set; }
  string LastModifiedBy { get; set; }
  DateTime LastModifiedAt { get; set; }
}

public override int SaveChanges() {
  var addedAuditedEntities = ChangeTracker.Entries<IAuditedEntity>()
    .Where(p => p.State == EntityState.Added)
    .Select(p => p.Entity);

  var modifiedAuditedEntities = ChangeTracker.Entries<IAuditedEntity>()
    .Where(p => p.State == EntityState.Modified)
    .Select(p => p.Entity);

  var now = DateTime.UtcNow;

  foreach (var added in addedAuditedEntities) {
    added.CreatedAt = now;
    added.LastModifiedAt = now;
  }

  foreach (var modified in modifiedAuditedEntities) {
    modified.LastModifiedAt = now;
  }

  return base.SaveChanges();
}
Run Code Online (Sandbox Code Playgroud)

  • EF数据库第一个实体使用partial关键字标记.这样可以轻松分配属性,而不会干扰生成的代码.只需创建一个新文件`AuditedEntries.cs`,其中包含`[IAuditedEntity]公共部分类TabImpianti {}` (3认同)

Bil*_*ani 16

这个 https://www.nuget.org/packages/TrackerEnabledDbContextnuget包

资料来源:https: //github.com/bilal-fazlani/tracker-enabled-dbcontext

  • 我喜欢你的方法,但缺少一个功能,即交易.我想在一个事务中将所有内容提交到数据库. (2认同)
  • @BilalFazlani GPL 强制您的所有代码都成为 GPL,因此如果您将其用于公司,则所有私有源代码都必须公开。我会将其更改为 MIT 或 Apache 许可证。https://www.quora.com/Whats-the-different-between-Apache-v2-0-and-MIT-license (2认同)

sam*_*amy 5

有一种方法可以执行此操作:您可以创建与对象上下文同名的部分类,并实现SaveChanges方法的覆盖.在此覆盖中,您可以查看将推送到数据库并处理它们的所有更改.

您可以按照自己喜欢的方式处理它们,在下面的示例中,我创建了一个IAutoTimestampEntity包含创建日期和修改日期的界面.此类型的任何对象都将随更改时间自动更新.

public override int SaveChanges(System.Data.Objects.SaveOptions options)
{
    var timestamp = DateTime.Now;

    foreach (var InsertedAutoTimestampEntity in ObjectStateManager.GetObjectStateEntries(System.Data.EntityState.Added).Select(ose => ose.Entity).OfType<IAutoTimestampEntity>())
    {
        InsertedAutoTimestampEntity.CreationDate = timestamp;
        InsertedAutoTimestampEntity.ModificationDate = timestamp;
    }

    foreach (var UpdatedAutoTimestampEntity in ObjectStateManager.GetObjectStateEntries(System.Data.EntityState.Modified).Select(ose => ose.Entity).OfType<IAutoTimestampEntity>())
    {
        UpdatedAutoTimestampEntity.ModificationDate = timestamp;
    }

    return base.SaveChanges(options);
}
Run Code Online (Sandbox Code Playgroud)

您可以使用相同的原则,也可以详细查看每个已更改实体的类型.我喜欢界面的声明方面.它允许您显式地公开自动化的一个方面,而不是让它由EF层静默完成.

如果你有一个DbContext,而不是一个ObjectContext,投你DbContextIObjectContextAdapter访问ObjectStateManager