Saturday, July 16, 2011

NHibernate concurrency checking on ASP.NET MVC

NHibernate concurrency handling on ASP.NET MVC is pretty boring, no need to introduce any work-around code :-)

Contrast with Entity Framework which need work-around(connected mode simulation) when it is working in disconnected state, NHibernate don't need any of that. NHibernate concurrent update is automatically handled behind the scene, no need to introduce any code to make NHibernate be informed which column(rowversion) is not needed on UPDATE's SET clause, what you just need is to inform NHibernate which property is your rowversion column, and no need to simulate connected mode.


Here's your typical user-friendly(and programmer-friendly if I may add) concurrent update handling with NHibernate:

[HttpPost]
public ActionResult Save(Song song)
{
    using (var s = Mapper.GetSessionFactory().OpenSession())
    using (var tx = s.BeginTransaction())
    {
        try
        {
            s.SaveOrUpdate(song); // SaveOrUpdate automatically fetches the primary key and row version

            tx.Commit();


            ModelState.Remove("SongId");
            // no need to issue ModelState.Remove on Version property; with byte array, ASP.NET MVC always get its value from the model, not from ModelState
            // ModelState.Remove("Version") 

        }
        catch(StaleObjectStateException ex)
        {                       
            s.Evict(song);
            var dbValues = s.Get<Song>(song.SongId);
            var userValues = song;
           


            if (dbValues == null)
            {
                ModelState.AddModelError("", "This record you are attempting to save is already deleted by other user");
                return;
            }

           
            if (dbValues.SongName != userValues.SongName)
                ModelState.AddModelError("SongName", "Current value made by other user: " + dbValues.SongName);

            
            if (dbValues.AlbumName != userValues.AlbumName)
                ModelState.AddModelError("AlbumName", "Current value made by other user: " + dbValues.AlbumName);

            ModelState.AddModelError("", 
                "The record you attempted to edit was already modified by another user since you last loaded it. Open the latest changes on this record");

        }
        catch (Exception ex)
        {
            ModelState.AddModelError("", ex.Message);
        }


        return View("Input", song);
    }
}

Get the DDL at http://www.ienablemuch.com/2011/07/entity-framework-concurrency-checking.html

Complete demo code: http://code.google.com/p/nh-concurrency-handling-on-aspnet-mvc-demo/downloads/list

Sample output:

No comments:

Post a Comment