Entity Framework DbContext SaveChanges() OriginalValue Incorrect

前端 未结 5 973
孤街浪徒
孤街浪徒 2020-12-03 21:51

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/2
相关标签:
5条回答
  • 2020-12-03 22:39

    The problem is not in the code you show here. The issue is that how you track entities. If you just create an entity object and calls Update on it EF framework just overwrite the existing value in db ( provided you supplied correct ID ). That is done for efficiency. So if you do:

    var company = new Company{Id = mySuppliedId, Name = newname};
    Context.Companies.Update(company);
    Context.SaveChanges(); 
    

    EF will go directly to DB in one shot and update all properties on the entity, without bringing anything back first. So it has no way of knowing the original values. If you change the code in your logic to something like:

    var company = Context.Companies.Where(c=>c.Id == mySuppliedId).FirstOrDefault();
    company.Name = newName;
    Context.SaveChanges() 
    

    Then your ChangeTracker code you showed above all of sudden starts working, as EF brought the data from DB first. It is however less efficient as you make and extra query.

    0 讨论(0)
  • 2020-12-03 22:41

    You can get data that you haven't committed yet.

    var Current = _dbContext.Entry(entity).GetDatabaseValues().ToObject();
    
    0 讨论(0)
  • 2020-12-03 22:50

    If you change

    dbEntry.OriginalValues.GetValue<object>(propertyName);
    

    to

    dbEntry.GetDatabaseValues().GetValue<object>(propertyName);
    

    then that works.

    0 讨论(0)
  • 2020-12-03 22:50

    I got this error when i override SaveChanges in context As follows

    public override int SaveChanges()
        {
            var changeInfo = ChangeTracker.Entries()
                .Select(t => new {
                    Original = t.OriginalValues.PropertyNames.ToDictionary(pn => pn, pn => t.OriginalValues[pn]),
                    Current = t.CurrentValues.PropertyNames.ToDictionary(pn => pn, pn => t.CurrentValues[pn]),
                }).ToList();
            return base.SaveChanges();
        }
    

    and when I cleared it fixed!

    ChangeTracker.Entries().ToList() in SaveChanges is wrong...

    0 讨论(0)
  • 2020-12-03 22:51

    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.

    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.

    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.

    0 讨论(0)
提交回复
热议问题