实体框架DbContext SaveChanges()OriginalValue不正确 [英] Entity Framework DbContext SaveChanges() OriginalValue Incorrect

查看:124
本文介绍了实体框架DbContext SaveChanges()OriginalValue不正确的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用EF 4.1实现AuditLog,通过覆盖SaveChanges()方法,如以下位置所述:

I am trying to implement an AuditLog using EF 4.1, by overriding the SaveChanges() method as discussed in the following places:

  • http://jmdority.wordpress.com/2011/07/20/using-entity-framework-4-1-dbcontext-change-tracking-for-audit-logging/
  • Entity Framework 4.1 DbContext Override SaveChanges to Audit Property Change

我在修改条目中遇到问题。每当我尝试获得相关资源的 OriginalValue 时,它总是与 CurrentValue 字段中的值一样。

I am having problems with the "modified" entries though. Whenever I attempt to get at the OriginalValue of the property in question, it always has the same value as it does in the CurrentValue field.

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

I first use this code, and it successfully identifies the Entries that are modified:

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

问题出在这个(缩写代码):

The problem is in this (abbreviated code):

    private List<AuditLog> 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<object>(propertyName),
                    dbEntry.CurrentValues.GetValue<object>(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<object>("Name").ToString()

                // the result will be "NewName" and not "OldName" as expected
             }
         }
    }

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

The strange thing is that the call to dbEntry.Property(propertyName).IsModified(); will return true in this case. It is just that the OriginalValue doesn't have the expected value inside. Would anyone be willing to help point me in the right direction? I cannot seem to get this to work correctly.

推荐答案

当EF从数据库中检索一个实体时,它会获取原始的快照该实体的所有属性的值。后来,随着对这些属性的值的改变,原始值将保持不变,而当前值将发生变化。

When EF retrieves an entity from the database it takes a snapshot of the original values for all properties of that entity. Later, as changes are made to the values of these properties the original values will remain the same while the current values change.

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

However, for this to happen EF needs to be tracking the entity throughout the process. In a web or other n-tier application, typically the values are sent to the client and the context used to query the entity is disposed. This means that the entity is now no longer being tracked by EF. This is fine and good practice.

应用程序发回后,使用客户端的值重建实体,然后重新附加到上下文并设置为修改状态。但是,默认情况下,从客户端返回的唯一值是当前值。原始值将丢失。通常情况下,这并不重要,除非您正在做出乐观的并发性,或者想要非常小心,只能更新真正改变的值。在这些情况下,原始值也应发送给客户端(通常作为Web应用程序中的隐藏字段),然后作为附加过程的一部分重新应用为原始值。在上面的例子中没有发生这种情况,这就是为什么原来的价值观没有如预期的那样显现。

Once the application posts back the entity is reconstructed using values from the client and then re-attached to the context and set into a Modified state. However, by default the only values that come back from the client are the current values. The original values are lost. Usually this doesn't matter unless you are doing optimistic concurrency or want to be very careful about only updating values that have really changed. In these cases the original values should also be sent to the client (usually as hidden fields in a web app) and then re-applied as the original values as a part of the attach process. This was not happening in the example above and this is why the original values were not showing as expected.

这篇关于实体框架DbContext SaveChanges()OriginalValue不正确的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆