实体框架6(代码优先)实体版本控制和审计

时间:2015-02-20 11:16:20

标签: c# sql-server entity-framework entity-framework-6

我正在考虑将Entity Framework 6.1.1与SQL Server 2008 R2结合使用。

目前我正在使用代码优先EF功能创建我的模型和数据库。我的基本用例是创建一个特定实体的所有更改的日志(ID是关键列),以帮助审计员跟踪所做的所有更改以及由谁进行的更改。 e.g:

|ID|Version|Created Date|Created By|Modified Date|Modified By|Modify Action| ... (rest of entity fields)
-------------------------------------------------------------------------------------------------------
| 4| 12    | 12-Mar-14  | tom      | 20-Feb-15   | jack      | Update      |
| 4| 11    | 12-Mar-14  | tom      | 14-Feb-15   | jill      | Update      |
| 4| 1     | 12-Mar-14  | tom      | 12-Mar-14   | tom       | Create      |

Entity Framework是否支持这种类型的数据库方案?如果是这样,我如何设置我的模型/解决方案以促进这一点?

我的另一个选择是截取SaveChanges()上对DbContext方法的所有调用,并将所有数据库更改记录到单独的Audit表中,但这可能会使检索信息更多具有挑战性的。

有关使用SQL Server和EF 6创建审计跟踪的任何帮助都将非常感激。

3 个答案:

答案 0 :(得分:7)

我使用了你提到的第二种方法,通过重载dbContext SaveChanges()方法:

public class MyContext : DbContext
{

 public int SaveChanges(int userId)
 {
    // Get all Added/Deleted/Modified entities (not Unmodified or Detached)
    foreach (var ent in this.ChangeTracker.Entries().Where(p => p.State ==  EntityState.Added 
    || p.State == EntityState.Deleted || p.State == EntityState.Modified))
    {

        foreach (AuditLog x in GetAuditRecordsForChange(ent, userId))
        {
            this.AuditLogs.Add(x);
        }
    }
    return base.SaveChanges();
  }
...

因此,如果我想记录一个特定的实体,我只需要调用重载的SaveChanges&传入UserId:

public void Update(StockCatalogueItem entity, int userId)
{
     _context.SaveChanges(userId);
}

我还有一个自定义DoNotLog属性,我用它来装饰我不想记录的实体属性。如果没有这个,日志记录可能会生成大量数据,因为每个实体修改等于一个db条目。

[DoNotLog]
public int CreatedBy { get; set; }

GetAuditRecordsForChange方法检查任何DoNotLog属性并返回List<AuditLog>,并将其保存在AuditLogs表中:

public class AuditLog
    {
        public int Id { get; set; }
        public int CreatedBy { get; set; }
        public DateTime CreatedOn { get; set; }
        public AuditEventType EventType { get; set; }
        public string TableName { get; set; }
        public int EntityId { get; set; }
        public string ColumnName { get; set; }
        public string Controller { get; set; }
        public string Action { get; set; }
        public string IPAddress { get; set; }
        public string OriginalValue { get; set; }
        public string NewValue { get; set; }
    }

答案 1 :(得分:3)

您可以查看Entity Framework Extended。它具有我用于将实体的所有更改记录到XML的审计功能。来自文档:

  

审核日志功能将随时捕获实体的更改   他们被提交到数据库。审核日志仅捕获   更改的实体以及这些实体上的属性   那些被改变了。记录前后值。   AuditLogger.LastAudit是保存此信息的地方,并且有一个   ToXml()方法,可以很容易地将AuditLog转换为xml for   易于存放。

     

可以通过实体上的属性或通过a来自定义AuditLog   Fluent配置API。

<强>更新

自2015年以来不再支持实体框架扩展。 有关此功能,请参阅Entity Framework Plus

答案 2 :(得分:0)

我想说这是DDD架构中提到的事件采购模式的一个很好的候选者。您永远不会更改实体表,但始终插入。

这样,当您需要特定版本时,您只需重新播放所有事件,并将它们应用于从版本0到您要查找的版本的实体。可以使用实体快照解决可伸缩性。

第二种方法也是有效的。

参考: http://microservices.io/patterns/data/event-sourcing.html