entity frameworkDbContext SaveChanges()OriginalValue不正确

我试图通过覆盖SaveChanges()方法使用EF 4.1实现AuditLog,如下面所述:

  • http://jmdority.wordpress.com/2011/07/20/using-entity-framework-4-1-dbcontext-change-tracking-for-audit-logging/
  • entity framework4.1 DbContext覆盖SaveChanges以审核属性更改

我遇到了“修改过”的条目问题。 每当我尝试获取相关属性的OriginalValue时,它总是具有与CurrentValue字段中相同的值。

我首先使用此代码,并成功识别修改的条目:

public int SaveChanges(string userID) { // Have tried both with and without the following line, and received same results: // ChangeTracker.DetectChanges(); foreach ( var ent in this.ChangeTracker .Entries() .Where(p => p.State == System.Data.EntityState.Added p.State == System.Data.EntityState.Deleted p.State == System.Data.EntityState.Modified)) { // For each change record, get the audit record entries and add them foreach (AuditLog log in GetAuditRecordsForChange(ent, userID)) { this.AuditLog.Add(log); } } return base.SaveChanges(); } 

问题在于此(缩写代码):

  private List GetAuditRecordsForChange(DbEntityEntry dbEntry, string userID) { if (dbEntry.State == System.Data.EntityState.Modified) { foreach (string propertyName in dbEntry.OriginalValues.PropertyNames) { if (!object.Equals(dbEntry.OriginalValues.GetValue(propertyName), dbEntry.CurrentValues.GetValue(propertyName))) { // It never makes it into this if block, even when // the property has been updated. } // If I updated the property "Name" which was originally "OldName" to the value "NewName" and then break here and inspect the values by calling: // ?dbEntry.OriginalValues.GetValue("Name").ToString() // the result will be "NewName" and not "OldName" as expected } } } 

奇怪的是调用dbEntry.Property(propertyName).IsModified(); 在这种情况下将返回true。 只是OriginalValue里面没有预期的值。 有人愿意帮我指出正确的方向吗? 我似乎无法使其正常工作。

当EF从数据库中检索实体时,它会获取该实体的所有属性的原始值的快照。 之后,当对这些属性的值进行更改时,原始值将保持不变,而当前值会更改。

但是,为了实现这一点,EF需要在整个过程中跟踪实体。 在web或其他n层应用程序中,通常将值发送到客户端,并且处理用于查询实体的上下文。 这意味着EF现在不再跟踪该实体。 这是很好的做法。

一旦应用程序回发,就使用来自客户端的值重建实体,然后重新附加到上下文并设置为修改状态。 但是,默认情况下,从客户端返回的唯一值是当前值。 原始值丢失。 通常这无关紧要,除非您正在进行乐观并发或者只是想要更新已经真正改变的值。 在这些情况下,原始值也应该发送到客户端(通常作为Web应用程序中的隐藏字段),然后作为附加过程的一部分重新应用为原始值。 在上面的示例中没有发生这种情况,这就是原始值未按预期显示的原因。

如果你改变了

 dbEntry.OriginalValues.GetValue(propertyName); 

 dbEntry.GetDatabaseValues().GetValue(propertyName); 

然后这工作。