Entity Framework 6 (code first) entity versioning and auditing

前端 未结 3 598
傲寒
傲寒 2020-12-30 09:15

I\'m looking at using Entity Framework 6.1.1 with SQL Server 2008 R2.

Currently I\'m creating my models and database using the code-first EF feature. My basic use-c

相关标签:
3条回答
  • 2020-12-30 09:54

    I have used the 2nd approach you mention, by overloading the dbContext SaveChanges() method:

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

    So if I want to log a particular entity, I just call the overloaded SaveChanges & pass in a UserId:

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

    I also have a custom DoNotLog attribute which I use to decorate the entity properties that I don't want to log. Without this, the logging could generate a huge amount of data, as each entity modification equals one db entry.

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

    The GetAuditRecordsForChange method does the checking for any DoNotLog properties and returns a List<AuditLog> which gets saved in the AuditLogs table:

    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; }
        }
    
    0 讨论(0)
  • 2020-12-30 09:57

    I would say this is a good candidate for the event sourcing pattern mentioned in a DDD architecture. You never change your entity table but always inserting.

    In that way, when you need an specific version you just re-play all events and apply them to the entity from version 0 to the version you are looking for. Scalability can be solved with entity snapshots.

    Second approach is also valid.

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

    0 讨论(0)
  • 2020-12-30 10:10

    You could look at Entity Framework Extended. It has audit functionality that I have used to log all changes to entities to XML. From the documentation:

    The Audit Log feature will capture the changes to entities anytime they are submitted to the database. The Audit Log captures only the entities that are changed and only the properties on those entities that were changed. The before and after values are recorded. AuditLogger.LastAudit is where this information is held and there is a ToXml() method that makes it easy to turn the AuditLog into xml for easy storage.

    The AuditLog can be customized via attributes on the entities or via a Fluent Configuration API.

    UPDATE:

    Entity Framework Extended is no longer supported since 2015. Please refer to Entity Framework Plus for this feature.

    0 讨论(0)
提交回复
热议问题