Monday, April 27, 2015

How to Fix the OptimisticConcurrencyException in MVC

In this post we describe Step by step How to Fix the OptimisticConcurrencyException in MVC.  
We take care here in just 5 minutes of the errors raised by the Entity Framework while the EDM (Entity Data Model) is confronting a database concurrency issue.

In short, when two or more users try to modify data simultaneously , SQL offers two types of Concurrency Control:
1) Pessimistic Concurrency : lock the data table in advance because someone for sure will try to   affect your changes simultaneously. Action to perform: LOCK the table!
2) Optimistic Concurrency : make your changes and let's hope none will try to alter the record in the meantime. Action to perform: raise an error if the record was altered in the meantime!

Our approach here will be: if indeed the record was altered from the original (AKA the "OptimisticConcurrencyException" was thrown), then we'll refresh the data and save your important updates with a "Client Wins" policy.


How to Fix the OptimisticConcurrencyException in MVC


To apply our approach, we'll use here a "Save(object itemToSave, int #noOfItemsToSave )" method, wrapping the context's SaveChanges().
We just add here a "catch" block to the C# method which tries to update an item to the database.
This way we enforce refreshing the item and saving all your changes overriding the refreshed data.
Therefore, add the following method to your Data Repository (copy-paste:) :

public bool Save(object target, int RecordsNumber)
        {
            try
            {
                return Context.SaveChanges() == RecordsNumber;
            }
            catch (OptimisticConcurrencyException)
            {
                ObjectContext ctx = ((IObjectContextAdapter)Context).ObjectContext;
                ctx.Refresh(RefreshMode.ClientWins, target);
                return Context.SaveChanges() == RecordsNumber;
            }
        }


As you see, the return value tells that all edited items have been successfully persisted to database.
Then you can use this method from your MVC Controller as follows:


 [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Edit(Blog blog)
        {
            if (ModelState.IsValid)
            {
                db.Update<Blog>(blog);
                db.Save(blog, 1);
                return RedirectToAction("Index");
            }
            ViewBag.BloggerID = new SelectList(db.Retrieve<Blogger>(null), "BloggerID", "Name", blog.BloggerID);
            return View(blog);
        }








Happy programming.....

      by Carmel Schvartzman


כתב: כרמל שוורצמן