我花了一些时间阅读一些关于审计跟踪的帖子和文章,但仍然无法解决这个问题。
我需要的是一个非常基本的审计系统,它会给我以下结果:
我试图在dbContext上覆盖SaveChanges事件,但我遇到了以下问题:
public override int SaveChanges()
{
foreach (DbEntityEntry<IAuditable> entry in ChangeTracker.Entries<IAuditable>())
{
if (entry.State == EntityState.Added)
{
// since the object was not added yet, if I write to log in here and
// for some reason SaveChanges fail, I will end up with a fake log entry
}
else if (entry.State == EntityState.Modified)
{
// same in here
}
}
return base.SaveChanges();
// here the state for all entries have changed to Unchanged or Detached.
// detached is probably the one that was deleted however the “Unchanged”
// could be new or modified records.
}
我知道我可以在数据库上使用触发器来实现这一点,但是我想把它保留在这里,所以我对它有更多的控制权,因为我不是一个SQL人员,在部署应用程序后我不会有对数据库有很大的控制权。
我确定我在这里错过了一些非常简单的东西。 我感谢任何帮助。
提前致谢。
答案 0 :(得分:2)
您可以随时检查上下文中是否有任何审核条目,并在调用SaveChanges时将其删除。它将解决您的第一个问题 - 您将始终在创建新审核条目之前将其删除。
使用DbContext API无法解决第二个问题。 DbContext API是ObjectContext API的简化,这种简化删除了复杂场景所需的方法。一种这样的方法是SaveChanges
的重载版本,能够不接受更改(不更改实体的状态)。
您可以将DbContext
转换为ObjectContext
至IObjectContextAdapter
。即使使用ObjectContext
,也不会是直截了当的:
// If you want to have audits in transaction with records you must handle
// transactions manually
using (TransactionScope scope = new TransactionScope(...))
{
ObjectContext context = ((IObjectContextAdapter)this).ObjectContext;
context.SaveChanges(SaveOptions.DetectChangesBeforeSave);
var audits = new List<Audit>();
// Now you must call your audit code but instead of adding audits to context
// you must add them to list.
// This is the reason why you must not add changes to context. You must accept
// old changes prior to adding your new audit records otherwise EF will perform
// changes again. If you add your entities to context and call accept before
// saving them your changes will be lost
context.AcceptAllChanges();
// Now add all audits from list to context
context.SaveChanges();
// Complete the transaction
scope.Complete();
}