4

I have a UI thread which enables the user to set certain properties of an entity.

I also have worker threads which will automatically modify properties of an entity that, importantly, the user does not have access to.

Would it be safe to have different DbContexts per thread and just depend on my programming to always avoid modifying the same property and then attempting to SaveChanges() on a context which has the same entity modified in different ways?

Or is there a safer way of doing this, i.e. a way in which it will be possible for a programmer to some day change the code such that the same property is modified from two different contexts safely? Or is this latter situation simply one where the programmer has to be careful/refactor around?

VMAtm
  • 26,645
  • 17
  • 75
  • 107
deed02392
  • 4,478
  • 2
  • 26
  • 48
  • Are you concerned with thread safety around EF data structures or is this about how you can make writes to one context propagate to other contexts? – usr Jun 04 '15 at 17:48
  • @usr This is about thread-safety and data integrity for entities I want to be able to modify from a UI thread while a long running task determines values for other properties of that entity. – deed02392 Jun 05 '15 at 09:34

1 Answers1

2

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.

VMAtm
  • 26,645
  • 17
  • 75
  • 107