Concurrency in Entity Framework:

Here you will learn to handle concurrency using EF 6 database-first approach for the underlying SQL Server database.

Entity Framework supports optimistic concurrency by default. EF saves an entity data to the database, assuming that the same data has not been changed since the entity was loaded. If it finds that the data has changed, then an exception is thrown and you must resolve the conflict before attempting to save it again.

To handle concurrency using EF 6 database-first approach, create a column with rowversion (timestamp) data type in the table in SQL Server. The rowversion (synonym timestamp) data type is just an incrementing binary numbers which is incremented for each insert or update operation performed on a table that contains a rowversion column.

Let's implement concurrency for the Student entity.

In order to check concurrency for the Student entity, the Student table must have a rowversion column. So, create a new column column named RowVersion in the Student table with timestamp datatype (timestamp is synonym data type of rowversion), as shown below:

Entity Framework 5.0 Tutorial

Now, create a new Entity Data Model as shown in Create Entity Data Model chapter or if you already have an EDM then update it by right clicking on designer -> Update Model From Database -> Refresh Student table. You will see the RowVersion property added in the Student entity in the designer view.

Now, you need to set the concurrency mode to fixed by right clicking on the RowVersion property of the Student entity on the designer and select Property and set Concurrency Mode to Fixed in the property window, as shown below:

Entity Framework 5.0 Tutorial

EF API will now include this RowVersion column in the where clause in each UPDATE command and if the rowversion value is different than existing value in the database then it will throw DbUpdateConcurrencyException.

The following example demonstrates handling concurrency exception:

Student student = null; 

using (var context = new SchoolDBEntities())
{
    student = context.Students.First();
}

//Edit student name
Console.Write("Enter New Student Name:");
student.StudentName = Console.ReadLine(); //Assigns student name from console

using (var context = new SchoolDBEntities())
{
    try
    {
        context.Entry(student).State = EntityState.Modified;
        context.SaveChanges();

        Console.WriteLine("Student saved successfully.");
    }
    catch (DbUpdateConcurrencyException ex)
    {
        Console.WriteLine("Concurrency Exception Occured.");
    }
}

Assume that there are two user executes the above code. User1 and User2 both gets the same Student entity. Now, User1 enters new student name and saves it before User2. So, User1 will get "Student saved successfully" message whereas User2 will get "Concurrency Exception Occured.".

Further Reading: