0

Need to compare the original value with the current value in order to do some updates on objects prior to save changes. How to get the original value of an object? The following does not work:

public ActionResult Edit(int id = 0)
{
    Project project = db.Projects.Find(id);
    ...
    db.Projects.Attach(project);  // ATTACH here
    ...
 }

 [HttpPost]
 public ActionResult Edit(Project project)
 {
     if (ModelState.IsValid)
     {
        db.Entry(project).State = EntityState.Modified;  // The STATE was DETACHED here...
        ...
  }

Is this a configuration issue, or did I miss something? Thanks in advance for any help!

Gerard
  • 2,649
  • 1
  • 28
  • 46

2 Answers2

1

The problem with your solution is the lifetime of the controller. By default a new instance of the controller is generated for each client request. This means that you need to load the original value inside the POST method of edit, because you cannot share the instance of your context.

I have edited the code sample after @Gerard's comment

[HttpPost]
public ActionResult Edit(Project project)
{
     if (ModelState.IsValid)
     {
         var original_value = db.Projects.Find(project.ProjectId);
         or
         var original_value_detached = db.Projects.AsNoTracking().Where(P => P.ProjectId == project.ProjectId).FirstOrDefault();
     }
 }

Or you write your own implementation of the controller factory to share you context between two requests, but you should consider requests from different clients. You can find an example here

Community
  • 1
  • 1
boindiil
  • 5,805
  • 1
  • 28
  • 31
  • Thanks, you're right of course! Back to AsNoTracking in my case. The code like db.Projects.AsNoTracking().Where(P => P.ProjectId == prj.ProjectId).FirstOrDefault(); works fine. Thought the original value was easily available too. – Gerard Aug 26 '13 at 19:46
  • Great! I have udpated my answer. Now it contains both solutions: attached and detached – boindiil Aug 27 '13 at 06:24
0

It looks like you are implementing concurrency. May be, you can try to catch your changes using DbUpdateConcurrencyException. Something like this:

try
        {
            ...
            db.SaveChanges();
        }
        catch (DbUpdateConcurrencyException ex)
        {
            var entry = ex.Entries.Single();
            var dbValue = (Project)entry.GetDatabaseValues().ToObject();
            if(dbValue.State == EntityState.Modified)
            {
             //***your code
             }
        }
Andrey Gubal
  • 3,481
  • 2
  • 18
  • 21