Awais Mahmood
Awais Mahmood

Reputation: 1336

How to check that which properties/entries are modified and which are not on Editing a record in EF 6

I am developing an MVC 5 application using EF 6. The auto-generated POST method for Edit is:

public ActionResult Edit([Bind(Include = "Id,Name,Address,Phone,SSNo,D1")] ABC abc)
{
     if (ModelState.IsValid)
     {
         db.Entry(abc).State = EntityState.Modified;
         db.SaveChanges();
     }
     return View(abc);
} 

Is there any procedure/method by which I can get that which entries are modified and what were the original values of those entries. I have tried the method marked as an answer in this question but it didn't get any changes although changes have been made, i.e. the loop does not iterates.

My code is:

 public ActionResult Edit([Bind(Include = "Id,Name,Address,Phone,SSNo,D1")] ABC abc)
 {
     if (ModelState.IsValid)
     {
          db.ABCs.Attach(abc);
          var myObjectState = ((IObjectContextAdapter)db).ObjectContext.ObjectStateManager.GetObjectStateEntry(abc);
          var modifiedProperties = myObjectState.GetModifiedProperties(); 
          foreach (var propName in modifiedProperties)
          {
                Console.WriteLine("Property {0} changed from {1} to {2}",
                propName,
                myObjectState.OriginalValues[propName],
                myObjectState.CurrentValues[propName]);
          }
          Console.ReadKey();
          db.Entry(abc).State = EntityState.Modified;
          db.SaveChanges();
          return Json(abc);
     }
     return View(abc);
 }

ABC model contains many values other than mentioned in method parameters, but I am only passing those which can be edited

What I am trying to do is to maintain a log in my database of all the changes made to a document. I want to include only the changes and the original values before modification in the log not the complete record.

How can I get this?

Upvotes: 3

Views: 1128

Answers (1)

Leonel Sanches da Silva
Leonel Sanches da Silva

Reputation: 7230

I implemented this extension method for you:

namespace YourProject.Extensions
{
    public static class ModelExtensions
    {
        public static IEnumerable<KeyValuePair<string, object>> ModifiedValues<T>(this T obj, T modifiedObject) 
        {
            foreach (var property in typeof(T).GetProperties().Where(p => !p.GetGetMethod().IsVirtual))
            {
                if (property.GetValue(obj).ToString() != property.GetValue(modifiedObject).ToString())
                {
                    yield return new KeyValuePair<string, object>(property.Name, property.GetValue(modifiedObject));
                }
            }
        }
    }
}

It's neither the fastest nor the most efficient, but worked in my tests.

Use:

var originalEntity = await db.Entities.AsNoTracking().FirstOrDefaultAsync(e => e.EntityId == modifiedEntity.EntityId);
var modifiedValues = originalEntity.ModifiedValues<MyEntity>(modifiedEntity).ToList();

Upvotes: 3

Related Questions