2

I have the following Model

public class CourseModel
{
    [Key]
    public int courseID { get; set; }
    ...
    public virtual ICollection<CourseMeetModel> meets { get; set; }
}

When I try to edit one of the entries and if the input is valid it works fine. However if the if its not valid it alerts the user of the mistakes. Once the user fixes the mistakes and tries to save i get the following exception.

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.

I have noticed this happens if the input fails the validation steps in my controller.

My Controller

public ActionResult EditCourseConfirmed(CourseModel course)
{
        CoursesDBContext db = new CoursesDBContext();
        bool valid = validateCouse(course); //If this fails and the course model is returned back to the view I get that error
        if (valid)
        {
                try
                {
                    db.Entry(course).State = EntityState.Modified;
                    db.SaveChanges();
                    Session[d.s_Clear] = false;
                    return RedirectToAction("Index");
                }
                catch (Exception e)
                {
                    ModelState.AddModelError(string.Empty, "Unable to save the course, please try again." + e.Message);
                    return View(course);
                }

        }

        return View(course);
}
keshav
  • 866
  • 11
  • 19

4 Answers4

2

Try this

try {
   context.SaveChanges();
} 
catch (OptimisticConcurrencyException) 
{
    context.Refresh(RefreshMode.ClientWins, db.table);
    context.SaveChanges();
}

Props: https://stackoverflow.com/a/6848729/1166147

Adding on to explain, per your comments. Thanks for your EF4 CTP5 tip. Glad this fixed it, please mark as accepted. When you get this error, something happened that changed the data (another user, etc) between load and update, there is a trigger causing problems, or if using a stored procedure it hit 0 recs. It is hard to know without more info. Is this the first update hit? Was there another update run first that succeeded before the user hit the error, modified, and then tried to go on without refreshing? Do you have any triggers? What is your degree of concurrency - did another user edit and save between this users' query and update? Read the link to the post I gave - someone mentioned a ReadOnlyAttribute in an entity key's metadata being replaced, which causes its value to become zero as a potential cause - I am not sure about this, but it makes sense -

(Modified from MSDN) By default, the Entity Framework implements an optimistic concurrency model. This means that locks are not held on data in the data source between when the data is queried and the data is updated, creating the potential for this error if another user modified the data. When this attribute is used, the Entity Framework checks for changes in the database before saving changes.

Any conflicting changes will cause an OptimisticConcurrencyException.

An OptimisticConcurrencyException can also occur when you define an Entity Data Model that uses stored procedures to make updates to the data source. In this case, the exception is raised when the stored procedure that is used to perform updates reports that zero rows were updated. SET NOCOUNT ON would fix thia.

Community
  • 1
  • 1
user1166147
  • 1,570
  • 2
  • 15
  • 17
  • 1
    Oh no I understand what the exception is and why you get it but here is the thing 1) Its still in the testing phase so I am running the app locally. 2) I was only logged in as one user (only had one browser open) and 3) We have implemented a locking system (which has been well tested) so there isn't any way to people could have tried to update the same record. So thats why I am not sure why error is accruing. And it only happens with this model and only after the first validation fails. – keshav May 29 '12 at 03:08
  • This doesn't work for DbContext. This is not the correct answer. – Doug Mar 17 '13 at 20:48
2

Thanks to user @user1166147 it was causing a dbupdate exception though I still don't know why ...

Since EF4 CTP5 DbContext doesnt have a refresh method i ended up doing this:

    try
    {
        db.SaveChanges();
    }
    catch (DbUpdateConcurrencyException e)
    {
        var entry = e.Entries.Single();
        entry.OriginalValues.SetValues(entry.CurrentValues);
        entry.CurrentValues.SetValues(entry.CurrentValues);
        db.SaveChanges();
    }

some more details here http://blogs.msdn.com/b/adonet/archive/2011/02/03/using-dbcontext-in-ef-feature-ctp5-part-9-optimistic-concurrency-patterns.aspx

keshav
  • 866
  • 11
  • 19
1

In your view make sure to add this

@Html.HiddenFor(m => m.courseID)
Prashanth Thurairatnam
  • 4,353
  • 2
  • 14
  • 17
1

I got the exception Reason was my entity has a Key with a mapping of

    HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);

and when i added a new Entity and supplied an id, at save time the context will think it is a modified Entity and not a new one, so i did not supply a value to the Key and at save time i check for the keys default value, from this i know if its new or modified

ramon22
  • 3,528
  • 2
  • 35
  • 48