[MVC3] ObjectContext.SaveChanges() — How to Use


ADO.NET Entity Framework stack

ADO.NET Entity Framework stack (Photo credit: Wikipedia)

Recently i have joined a Facebook Group The Dev circle, which is a group of likeminded developers who wish to learn, code and grok!

 

One member is starting out using Microsoft’s ORM Entity Framework (EF) and wanted to know how to update his Entities. This is easy within EF, as there is an method called SaveChanges() which will do the following:

 

Persists all updates to the data source and resets change tracking in the object context.

So how do we use it? Well with all Data Connections we need to use a “using” statement and we also need to make sure we catch the required Exceptions detailed in the MSDN documentation, one in particular is OptmisticConcurrencyException which allows us to resolve any concurrency conflicts based on parameters we pass to another method Refresh().

 

Take for e.g. a controller i have in a MVC3 Project which employs EF. Here is the code:

 

// POST: /LedgerUser/Create[Bind(Prefix = "LedgerUser")]

 [HttpPost]
 public ActionResult Create(bool Thumbnail,LedgerUser LedgerUser, 
HttpPostedFileBase imageLoad2) { var Avatar = new Accounts.Models.Image(); //--Handle the image first. if (imageLoad2 != null) { using (System.Drawing.Image img =
System.Drawing.Image.FromStream(imageLoad2.InputStream)) { //--Initialise the size of the array byte[] file = new byte[imageLoad2.InputStream.Length]; //--Create a new BinaryReader and set the InputStream for the
//--Images InputStream to the //--beginning, as we create the img using a stream.
BinaryReader reader = new BinaryReader(imageLoad2.InputStream); imageLoad2.InputStream.Seek(0, SeekOrigin.Begin); //--Load the image binary. file = reader.ReadBytes((int)imageLoad2.InputStream.Length); //--Create a new image to be added to the database Avatar.id = Guid.NewGuid(); Avatar.TableLink = LedgerUser.id; Avatar.RecordStatus = " "; Avatar.FileSize = imageLoad2.ContentLength; Avatar.FileName = imageLoad2.FileName; Avatar.FileSource = file; Avatar.FileContentType = imageLoad2.ContentType; Avatar.FileHeight = img.Height; Avatar.FileWidth = img.Width; Avatar.CreatedDate = DateTime.Now; //-- Now we create the thumbnail and save it. if (Thumbnail == true) { byte[] thumbnail =
Images.CreateThumbnailToByte(imageLoad2.InputStream, 100, 100); Avatar.ThumbnailSource = thumbnail; Avatar.ThumbnailFileSize = thumbnail.Length; Avatar.ThumbnailContentType =
Files.GetContentType(imageLoad2.FileName); Avatar.ThumbnailHeight = Images.FromByteHeight(thumbnail); Avatar.ThumbnailWidth = Images.FromByteWidth(thumbnail); } else { byte[] thumbnail = new byte[0]; Avatar.ThumbnailSource = thumbnail; Avatar.ThumbnailFileSize = 0; Avatar.ThumbnailContentType = " "; Avatar.ThumbnailHeight = 0; Avatar.ThumbnailWidth = 0; } } } if (!ModelState.IsValid) { ModelState.ModelStateErrors(); } if (ModelState.IsValid) { using (AccountsEntities context = new AccountsEntities()) { try { //--Save the LedgerUser context.LedgerUsers.AddObject(LedgerUser); context.SaveChanges(); } catch (OptimisticConcurrencyException) { context.Refresh(RefreshMode.ClientWins, LedgerUser); context.SaveChanges(); Console.WriteLine
("OptimisticConcurrencyException " + "handled and changes saved"); } catch (UpdateException ex) { Console.WriteLine(ex.ToString()); } try { //--Save the Image context.Images.AddObject(Avatar); context.SaveChanges(); return RedirectToAction("Index", "Home"); } catch (OptimisticConcurrencyException) { context.Refresh(RefreshMode.ClientWins, Avatar); context.SaveChanges(); Console.WriteLine
("OptimisticConcurrencyException Avatar" + "handled and changes saved"); } catch (UpdateException ex) { Console.WriteLine(ex.ToString() + " 2 "); } } } var userTypes = new SelectList(db.UserTypes, "id", "Description"); var ledgerUser = new LedgerUser() { id = LedgerUser.id, RecordStatus = LedgerUser.RecordStatus, CreatedDate = LedgerUser.CreatedDate, DateOfBirth = LedgerUser.DateOfBirth }; var viewModel = new LedgerUserViewModel() { UserTypes = userTypes, LedgerUser = ledgerUser }; return View(viewModel); }

 

So what is this controller doing:

  • Create new Ledger Users and their Avatar Images.
  • These are persisted using an AccountsEntities ObjectContext
  • I only save the the LedgerUser and Avatar if the ModelState.IsValid . I then try and SaveChanges.
  • I catch the required Exceptions
  • Return the viewModel if the SaveChanges() fails.

There is a good MSDN Article How to: Manage Data Concurrency in the Object Context to read here.

This approach should be used for most EF persistence.

 

 

 

Enhanced by Zemanta

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s