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. Related content feature 14 great preprocessors for developers who love to code Sometimes it seems like the rules of programming are designed to make coding a chore. Here are 14 ways preprocessors can help make software development fun again. By Peter Wayner Nov 18, 2024 10 mins Development Tools Software Development feature Designing the APIs that accidentally power businesses Well-designed APIs, even those often-neglected internal APIs, make developers more productive and businesses more agile. By Jean Yang Nov 18, 2024 6 mins APIs Software Development news Spin 3.0 supports polyglot development using Wasm components Fermyon’s open source framework for building server-side WebAssembly apps allows developers to compose apps from components created with different languages. By Paul Krill Nov 18, 2024 2 mins Microservices Serverless Computing Development Libraries and Frameworks news Go language evolving for future hardware, AI workloads The Go team is working to adapt Go to large multicore systems, the latest hardware instructions, and the needs of developers of large-scale AI systems. By Paul Krill Nov 15, 2024 3 mins Google Go Generative AI Programming Languages Resources Videos