C# Entity Framework创建审核历史记录

4
我正在使用Entity Framework构建一个基本的存储库来添加/删除/更新客户记录。
我想要的一件事是能够进行客户行审计,以便我有第二个表CustomerAudit,每次添加/更新/删除行时都应该添加一个条目。在旧的世界中,这将通过数据库触发器进行处理,例如在更新/删除/插入等操作时。现在,我正在尝试通过重写DBContext对象的SaveChanges()方法,利用ChangeTracker对象并使用其根据正在保存/更新的数据创建审核记录,并插入当前日期时间和实际行之间的记录。代码如下。
我的问题是,当您更新或删除时,这样做很好,因为它会将最新记录写入审核表,该表将包含更新值或删除之前的最终值,以及执行此操作的当前时间戳。
但是,当您添加记录时,它会在审核表中插入一条记录,但由于实际行尚未插入(具有identity insert),因此您尚未拥有CustomerId,因此它会插入具有正确数据但CustomerId为0的审核记录,这对审核无用。
您是否有任何想法可以使审核对添加记录起作用?
 public class CustomerDbContext : DbContext 
    {
        public CustomerDbContext()
        {
            Database.SetInitializer(new CreateDatabaseIfNotExists<CustomerDbContext>());
        }

        public DbSet<Customer> Customers { get; set; }
        public DbSet<CustomerAudit> CustomerAudits { get; set; }

        public override int SaveChanges()
        {
            // Get all Added/Deleted/Modified entities (not Unmodified or Detached)
            foreach (var ent in ChangeTracker.Entries().Where(p => p.State == System.Data.EntityState.Added || p.State == System.Data.EntityState.Deleted || p.State == System.Data.EntityState.Modified))
            {
                var auditRecord = GetAuditRecord(ent);
                if (auditRecord != null)
                    CustomerAudits.Add(auditRecord);                
            }

            // Call the original SaveChanges(), which will save both the changes made and the audit records
            return base.SaveChanges();
        }

        private static CustomerAudit GetAuditRecord(DbEntityEntry dbEntry)
        {
            var changedRecord = dbEntry.Entity as Customer;
            return changedRecord == null ? null : new CustomerAudit(changedRecord);
        }
    }

另一个解决方案可能对您来说现在不切实际,因为您已经创建了模型,那就是将PK类型从int更改为GUID。当实例化Customer实体时,将生成GUID,并且您将提前知道其值(customer.Id == '4705b72f-1e5b-4d0c-90d9-c235750f8b13')。 - Catalin
2个回答

3

获取所有条目并将它们保存到列表中,然后保存更改,将base.SaveChanges()调用的结果存储在变量中,接着遍历你创建的更改列表并从中创建审核实体,最后return base.SaveChanges() + yourPriorSaveChangesResultVariable;


1

@Rob G的答案虽然解决了问题,但是这里的审计是在两个事务中完成的。第一个是插入客户行,第二个是将CustomerId插入到CustomerAudit表中。

我认为最好在这些表中创建一个外键关系,将生成相同的CustomerId并且在同一事务中也会在CustomerAudit表中生成。

我是第一次在stackoverflow分享我的想法,但已经从中获得帮助很长时间了。

如果有任何评论,请留言。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接