1

Problem

I want to save the attributes of a model that have changed when a user edits them. Here's what I want to do ...

  1. Retrieve edited view model
  2. Get domain model and map back updated value
  3. Call the update method on repository
  4. Get the "old" domain model and compare values of the fields
  5. Store the changed values (in JSON) into a table

However I am having trouble with step number 4. It seems that the Entity Framework doesn't want to hit the database again to get the model with the old values. It just returns the same entity I have.

Attempted Solutions

I have tried using the Find() and the SingleOrDefault() methods, but they just return the model I currently have.

Example Code

private string ArchiveChanges(T updatedEntity)
{
    //Here is the problem!
    //oldEntity is the same as updatedEntity
    T oldEntity = DbSet.SingleOrDefault(x => x.ID == updatedEntity.ID);

    Dictionary<string, object> changed = new Dictionary<string, object>();

    foreach (var propertyInfo in typeof(T).GetProperties())
    {
        var property = typeof(T).GetProperty(propertyInfo.Name);

        //Get the old value and the new value from the models
        var newValue = property.GetValue(updatedEntity, null);
        var oldValue = property.GetValue(oldEntity, null);

        //Check to see if the values are equal
        if (!object.Equals(newValue, oldValue))
        {
            //Values have changed ... log it
            changed.Add(propertyInfo.Name, newValue);
        }
    }

    var ser = new System.Web.Script.Serialization.JavaScriptSerializer();
    return ser.Serialize(changed);
}

public override void Update(T entityToUpdate)
{
    //Do something with this
    string json = ArchiveChanges(entityToUpdate);

    entityToUpdate.AuditInfo.Updated = DateTime.Now;
    entityToUpdate.AuditInfo.UpdatedBy = Thread.CurrentPrincipal.Identity.Name;

    base.Update(entityToUpdate);
}
Stefan Bossbaly
  • 6,682
  • 9
  • 53
  • 82
  • Is this code after you have updated the reporistory? Thats what it sounds like, from your steps. If so, then yes you will get the new model; you updated the old model. If you want to do this, you need to get the old model BEFORE updating. – Kyeotic Jul 06 '12 at 20:04
  • @Tyrsius no its before. I added the calling method for a clearer picture. – Stefan Bossbaly Jul 06 '12 at 20:07
  • 1
    The entity you are working on / updating is attached to the context (tracked). Meaning that if you modify it, it will go to a Modified state (meaning that when SaveChanges is called it will do the Update in DB). However when only querying the entity (SingleOrDefault call), as the entity is attached to the context (in memory cache), it will be retrieved directly from the context and no round trip to DB will be made. You need to Detach the entity from the current context if you want to retrieve it from DB (and then reattach it so that the call to SaveChanges will actually update DB). – darkey Jul 06 '12 at 20:39

1 Answers1

2

The issue is that Entity Framework cache's the objects it reads in the DbSet. So when you request the object the second time, it isn't going to the database because it already has loaded it.

However, the good news is that Entity automatically tracks the original values. See this question for information on how to get them: How to get original values of an entity in Entity Framework?

Community
  • 1
  • 1
Jeff Siver
  • 7,434
  • 30
  • 32