0

I have three EntityFramework (4.3) objects, a Member, Address and a State. They look like this:

public class Member
{
    public int Id { get; set; }
    public virtual Address Address { get; set; }
    /*other properties removed for brevity*/
}

public class Address
{
    public int Id { get; set; }
    public virtual State State { get; set; }
    /*other properties removed for brevity*/
}

public class State
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Abbreviation { get; set; }
    public virtual ICollection<Address> Address { get; set; }
}

When I update the address relationship, everything works fine. See code below:

[HttpPost]
public ActionResult Update(MemberUpdateModel model)
{
    if (!ModelState.IsValid)
    {
        model.SetStateSelectList(_db, model.SelectedStateId);
        return View(model);
    }

    _db.Entry(model.Member).State = EntityState.Modified;
    _db.Entry(model.Member.Address).State = EntityState.Modified;

    _db.SaveChanges(); // works

    return RedirectToAction("Index");
}

Then I add in the update for the Address/State relationship like this:

[HttpPost]
public ActionResult Update(MemberUpdateModel model)
{
    if (!ModelState.IsValid)
    {
        model.SetStateSelectList(_db, model.SelectedStateId);
        return View(model);
    }

    _db.Entry(model.Member).State = EntityState.Modified;
    _db.Entry(model.Member.Address).State = EntityState.Modified;

    // added for address/state relationship
    var selectedState = _db.States.FirstOrDefault(q => q.Id == model.SelectedStateId);
    model.Member.Address.State = selectedState;

    _db.SaveChanges();

    return RedirectToAction("Index");
}

When we run the above code, we get the following error:

Store update, insert, or delete statement affected an unexpected number of rows (0). Entities may have been modified or deleted since entities were loaded. Refresh ObjectStateManager entries.

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code. 

Exception Details: System.Data.OptimisticConcurrencyException: Store update, insert, or delete statement affected an unexpected number of rows (0). Entities may have been modified or deleted since entities were loaded. Refresh ObjectStateManager entries.

What am I doing wrong to cause this behavior?

quakkels
  • 11,676
  • 24
  • 92
  • 149
  • Just out of curiosity, what happens when you move the EntityStat.Modified lines in your Address Update method to *after* you make the changes (right before the _db.SaveChanges();)? – Gromer Aug 16 '12 at 19:30
  • @Gromer - when we move those lines, then the error goes away, but state does not get updated at all. – quakkels Aug 16 '12 at 19:44

2 Answers2

0

"OptimisticConcurrencyException" looks to be a meaningfule clue here. This discussion may be useful.

Community
  • 1
  • 1
Mark Maslar
  • 1,121
  • 4
  • 16
  • 28
  • I found that discussion while googling. Our keys are all being set. We are testing locally on a dev machine. Perhaps our own methods are getting in the way like that answer suggests, but I don't see where. Can you help? – quakkels Aug 16 '12 at 19:47
  • Is this line necessary? _db.Entry(model.Member).State = EntityState.Modified; Perhaps not necessary to set both that and .Address to Modified? – Mark Maslar Aug 16 '12 at 19:57
0

We changed the update action to query for the existing data first, and then update the objects using the posted data.

[HttpPost]
public ActionResult Update(MemberUpdateModel model)
{
    if (!ModelState.IsValid)
    {
        model.SetStateSelectList(_db, model.SelectedStateId);
        return View(model);
    }

    var newModel = new MemberUpdateModel();
    newModel.Member = _db.Members.Include("Address").FirstOrDefault(q => q.Id == model.Member.Id);
    newModel.Member.Address.State = _db.States.FirstOrDefault(q => q.Id == model.SelectedStateId);

    bool success = TryUpdateModel(newModel);
    if (success)
    {
        _db.SaveChanges();
    }
    else
    {
        throw new Exception("TryUpdateModel() Failed");
    }

    return RedirectToAction("Index");
}

This works great.

quakkels
  • 11,676
  • 24
  • 92
  • 149