Entity Framework Thread Safety

2020-01-26 08:08发布

问题:

The context objects generated by Entity Framework are not thread-safe.

What if I use two separate entity contexts, one for each thread (and call SaveChanges() on each) - will this be thread-safe?

// this method is called from several threads concurrently
public void IncrementProperty()
{
   var context = new MyEntities();

   context.SomeObject.SomeIntProperty++;
   context.SaveChanges();
}

I believe entity framework context implements some sort of 'counter' variable which keeps track of whether the current values in the context are fresh or not.

  1. With the code above - called from separate threads - do I still need to lock around the increment/savechanges?
  2. If so, what is the preferred way to accomplish this in this simple scenario?

回答1:

More that one thread operating on a single Entity Framework context is not thread safe.

A separate instance of context for each thread is thread-safe. As long as each thread of execution has its own instance of EF context you will be fine.

In your example, you may call that code from any number of threads concurrently and each will be happily working with its own context.

However, I would suggest implementing a 'using' block for this as follows:

// this method is called from several threads concurrently
public void IncrementProperty()
{
   using (var context = new MyEntities())
   {
      context.SomeObject.SomeIntProperty++;
      context.SaveChanges();
   }
}


回答2:

You can use the factory approach inject your DbContext as a factory instead of an instance perse, take a look at this: https://github.com/vany0114/EF.DbContextFactory

It's safer and you avoid to hardcode the instance creation into your repositories.

http://elvanydev.com/EF-DbContextFactory/

There is an extension to Ninject to do that in a very easy way, just calling the method kernel.AddDbContextFactory<YourContext>(); also you need to change your repository by receiving a Func<YourContext>



回答3:

I believe "SomeObject.SomeIntProperty" is static. This has nothing to do with Entity being threadsafe. If you are writing to a Static variables in a multithreaded environment you should always wrap them with a double check lock to ensure thread safety.