2014-11-14 28 views
2

我正在根據實體框架中的上下文對象中跟蹤的更改編寫AuditLog。通過簡單注入器攔截/裝飾實體框架的DbContext.SaveChanges()

我需要能夠攔截電話Context.SaveChanges(),因爲我然後遍歷Context.ChangeTracker.Entries()並將它們記錄到我的AuditLog。

我需要能夠在DbContext本身上做到這一點,因爲我都有可能通過我的UnitOfWork直接獲取DbContext和PerWebRequest。

我試圖通過一個裝飾器來解決這個問題,它並不適合我!

public class AuditLogSaveChangesInKNContextDecorator : DbContext 
{ 
    DbContext _context; 
    IHandleCommand<AddAuditLogEntriesFromTrackedChangesAndSaveChangesCommand> _handler; 

    public AuditLogSaveChangesInKNContextDecorator(DbContext context, 
     IHandleCommand<AddAuditLogEntriesFromTrackedChangesAndSaveChangesCommand> handler) 
    { 
     _context = context; 
     _handler = handler; 
    } 

    public override int SaveChanges() 
    { 
     var changes = base.SaveChanges(); 

     _handler.Handle(new AddAuditLogEntriesFromTrackedChangesAndSaveChangesCommand { 
      Context = _context 
     }); 

     return changes; 
    } 
} 

任何想法?

回答

9

你在做什麼似乎對我來說很合適。 「攔截」SaveChanges的呼叫的唯一方法是重寫該方法;它是虛擬的。例如:

public class MyDbContext : DbContext 
{ 
    public event Action<MyDbContext> SavingChanges = _ => { }; 

    public override int SaveChanges() 
    { 
     // Notify objects that want to know, that we are gonna save some stuff 
     this.SavingChanges(this); 

     // Call the actual SaveChanges method to apply the changes to the database 
     return base.SaveChanges(); 
    } 
} 

通過使用一個事件,我們可以添加任何行爲(依賴注入)到MyDbContext,而不必知道它這方面。例如:

container.RegisterPerWebRequest<MyDbContext>(() => 
{ 
    var context = new MyDbContext(); 
    context.SavingChanges += UpdateEntities; 
    return context; 
}); 

private static void UpdateEntities(MyDbContext db) 
{ 
    var addedEntities = 
     from entry in db.ChangeTracker.Entries() 
     where entry.State == EntityState.Added 
     select entry.Entity as IEntity; 

    db.AuditTrailEntries.AddRange(
     from entity in addedEntities 
     select new AuditTrailEntry 
     { 
      EntityId = entity.Id, 
      Type = entity.GetType().Name 
     }); 
} 
1

你打電話給SaveChanges()在錯誤DbContext

相反的:

var changes = base.SaveChanges(); 

您應該使用:

var changes = _context.SaveChanges(); 

由於_context是,你想跟蹤DbContext,你需要做的是一個保存,而不是你的裝飾器對象。