Theoretical part
There are three ways to resolve the concurrency issues in the multi-threading environment:
- pessimistic, this can easily be done with
locks
for an item being edited - no one else can edit the item already being edited. This is very hard to implement approach, and this way is quite bad from performance view - all the editing threads are waiting for a single writer, and just wasting the system resources.
- optimistic, this is default way to resolve the issues. The main idea is that you continue the operation until you have a success. There are a lot of algorithm already introduced, I encourage you to read whole wiki-article and, may be, some additional references and/or books on theme.
- semi-optimistic, this is a hybrid approach, this way is being used if you need to
lock
some operations, but not all.
Practice part
Entity framework authors encourage you to use the optimistic way in your app. The simple use-case is to add RowVersion
or similar-named property to your model, and catch the DBUpdatedException
during the UPDATE
.
You can use the Code-First
solution, like this:
[Timestamp]
public byte[] RowVersion { get; set; }
or Database-First
solution (add column with database editor):
![enter image description here]()
After that, your code for a simple case will be like:
using (var context = new SchoolDBEntities())
{
try
{
context.Entry(student1WithUser2).State = EntityState.Modified;
context.SaveChanges();
}
catch (DbUpdateConcurrencyException ex)
{
Console.WriteLine("Optimistic Concurrency exception occured");
}
}
As I understood, you have to examine some properties of your data source, so I suggest you to read a great article regarding such use-cases (it is about an MVC-application, but I'm sure that you can manage out the main idea).
You can also find several articles regarding concurrency in Entity Framework on MSDN:
- Optimistic Concurrency Patterns
- Resolving optimistic concurrency exceptions with Reload (database wins)
- Resolving optimistic concurrency exceptions as client wins
- Custom resolution of optimistic concurrency exceptions
- Custom resolution of optimistic concurrency exceptions using objects
- Working with Property Values
- Getting and setting the current or original value of an individual property
- Getting and setting the current value of an unmapped property
- Checking whether a property is marked as modified
- Marking a property as modified
- Reading current, original, and database values for all properties of an entity
- Setting current or original values from another object
- Setting current or original values from a dictionary
- Setting current or original values from a dictionary using Property
- Creating a cloned object containing current, original, or database values
- Getting and setting the current or original values of complex properties
- Using
DbPropertyValues
to access complex properties
As you can see, this situation relies completely on a developer side, and you have a great amount of patterns you may choose to resolve you concurrent issues by yourself.