【问题标题】:Intercepting and logging changes with EF 4.2 code first首先使用 EF 4.2 代码拦截和记录更改
【发布时间】:2011-12-01 23:15:22
【问题描述】:

我花了一些时间阅读了一些关于审计跟踪的帖子和文章,但仍然无法弄清楚。

我需要的是一个非常基本的审计系统,它会给我如下结果:

  • 客户“John Doe”已被“用户”删除
  • 客户“Jane Doe”是由“其他用户”创建的
  • 来自“John Doe”的地址已被“用户”修改
  • 客户“Jane Doe”已被“其他用户”删除

我试图覆盖 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 专家,并且在部署应用程序后我不会拥有对数据库的控制如此之大。

我确定我在这里遗漏了一些非常简单的东西。 感谢您的帮助。

提前致谢。

【问题讨论】:

    标签: entity-framework entity-framework-4 ef-code-first tracking ef4-code-only


    【解决方案1】:

    您始终可以检查上下文中是否有任何审核条目,并在调用 SaveChanges 时将其删除。它将解决您的第一个问题 - 您将始终在创建新条目之前删除以前的审核条目。

    第二个问题不能用 DbContext API 解决。 DbContext API 是 ObjectContext API 的简化,这种简化删除了复杂场景所需的方法。一种这样的方法是SaveChanges 的重载版本,它能够不接受更改(不更改实体的状态)。

    您可以通过IObjectContextAdapter 将DbContext 转换为ObjectContext。即使使用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(); 
    }
    

    【讨论】:

    • 性能怎么样?将 DbContext 转换为 ObjectContext 后保存数据不慢吗?
    • @Saber:DbContext 内部使用 ObjectContext,因此不会对性能产生任何影响。
    猜你喜欢
    • 2013-07-28
    • 1970-01-01
    • 2016-06-06
    • 1970-01-01
    • 1970-01-01
    • 2020-11-30
    • 2014-07-06
    • 2020-04-07
    相关资源
    最近更新 更多