joydip_kanjilal
Contributor

How to handle concurrency conflicts in Entity Framework

opinion
Jun 17, 20164 mins
Software Development

Explore ways to handle concurrency conflicts to maintain data integrity and data consistency when working with Entity Framework

Concurrency handling can be used to maintain data integrity and data consistency when multiple users access the same resource concurrently. Concurrency violations can occur when you have interdependent transactions, i.e. transactions that are dependent on one another and try to access the same resource.

Handling concurrency conflicts in Entity Framework

Let’s now understand how each of these strategies work in Entity Framework. In the pessimistic concurrency, when a particular record is being updated, all other concurrent updates on the same record will be put on hold until the current operation is complete and the control is relinquished back so that other concurrent operations can continue. In the optimistic concurrency mode, the last saved record, “wins.” In this mode, it’s assumed that resource conflicts due to concurrent accesses to a shared resource are unlikely, but, not impossible.

Incidentally, Entity Framework provides support for optimistic concurrency by default. Entity Framework doesn’t provide support for pessimistic concurrency out of the box. Let’s now understand how Entity Framework resolves concurrency conflicts when working in the optimistic concurrency (default mode).

When working with optimistic concurrency handling mode, you would typically want to save data to your database assuming that the data hasn’t changed since it was loaded in the memory. Note that when your attempt to save changes to the database using the SaveChanges method on your data context instance, a DbUpdateConcurrencyException will be thrown. Let’s now understand how we can fix this.

To check for concurrency violation you can include a field in your entity class and mark it using Timestamp attribute. Refer to the entity class given below.

public class Author

   {

       public Int32 Id { get; set; }

       public string FirstName { get; set; }

       public string LastName { get; set; }

       public string Address { get; set; }

       [Timestamp]

       public byte[] RowVersion { get; set; }

   }

Now, Entity Framework supports two concurrency modes: None and Fixed. While the former implies that no concurrency checks would be performed when updating the entity, the latter implies that the original value of the property will be considered while executing WHERE clauses at the time when updates or deletes of data are done. If you have a property that is marked using Timestamp, the concurrency mode is considered as Fixed which in turn implies that the original value of the property would be considered in the WHERE clause of any updates or deletes of data for that particular entity.

To resolve optimistic concurrency conflicts, you can take advantage of the Reload method to update the current values in your entity residing in the memory with the recent values in the database. Once reloaded with the updated data, you can attempt to persist your entity again in the database. The following code snippet illustrates how this can be achieved.

using (var dbContext = new IDBDataContext())

{

     Author author = dbContext.Authors.Find(12);

     author.Address = "Hyderabad, Telengana, INDIA";

       try

         {

             dbContext.SaveChanges();

         }

         catch (DbUpdateConcurrencyException ex)

         {

             ex.Entries.Single().Reload();

             dbContext.SaveChanges();

         }

}

Note that you can leverage the Entries method on the DbUpdateConcurrencyException instance to retrieve the list of DbEntityEntry instances corresponding to the entities that could not be updated when a SaveChanges method was called to persist the entities to the database.

Now, the approach we just discussed is often called “stored wins” or “database wins” since the data contained in the entity is overwritten by the data available in the database. You can also follow another approach called “client wins”. In this strategy, the data from the database is retrieved to populate the entity. In essence, the data retrieved from the underlying database is set as the original values for the entity. The following code snippet illustrates how this can be achieved.

try

{

     dbContext.SaveChanges();

}

catch (DbUpdateConcurrencyException ex)

{

   var data = ex.Entries.Single();

   data.OriginalValues.SetValues(data.GetDatabaseValues());

}

You can also check if the entity you are trying to update is already deleted by another user or, has already been updated by another user. The following code snippet illustrates how you can do this.

catch (DbUpdateConcurrencyException ex)

{

   var entity = ex.Entries.Single().GetDatabaseValues();

   if (entity == null)

   {

         Console.WriteLine("The entity being updated is already deleted by another user...");

   }

   else

   {

         Console.WriteLine("The entity being updated has already been updated by another user...");

   }

}

If your database table doesn’t have a timestamp column or rowversion, you can take advantage of the ConcurrencyCheck attribute to detect concurrency conflicts when using Entity Framework. Here’s how this property is used.

[Table("Authors"]

public class Author

{

   public Author() {}

   [Key]

   public int Id { get; set; }

   [ConcurrencyCheck]

   public string FirstName { get; set; }

   public string LastName { get; set; }

   public string Address { get; set; }

}

In doing do, SQL Server would automatically include AuthorName when executing update or delete statements in the database.

joydip_kanjilal
Contributor

Joydip Kanjilal is a Microsoft Most Valuable Professional (MVP) in ASP.NET, as well as a speaker and the author of several books and articles. He received the prestigious MVP award for 2007, 2008, 2009, 2010, 2011, and 2012.

He has more than 20 years of experience in IT, with more than 16 years in Microsoft .Net and related technologies. He has been selected as MSDN Featured Developer of the Fortnight (MSDN) and as Community Credit Winner several times.

He is the author of eight books and more than 500 articles. Many of his articles have been featured at Microsoft’s Official Site on ASP.Net.

He was a speaker at the Spark IT 2010 event and at the Dr. Dobb’s Conference 2014 in Bangalore. He has also worked as a judge for the Jolt Awards at Dr. Dobb's Journal. He is a regular speaker at the SSWUG Virtual Conference, which is held twice each year.

More from this author