Entity Framework Потокобезопасность - PullRequest
34 голосов
/ 16 декабря 2010

Объекты контекста, созданные Entity Framework, не являются поточно-ориентированными.

Что если я использую два отдельных контекста сущности, по одному для каждого потока (и вызову SaveChanges() для каждого) - это будет потокобезопасным?

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

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

Я полагаю, что контекст структуры сущности реализует своего рода переменную 'counter', которая отслеживает, являются ли текущие значения в контексте свежими или нет.

  1. С приведенным выше кодом - вызывается из отдельных потоков - мне все еще нужно заблокировать инкремент / сохранения?
  2. Если это так, каков предпочтительный способ сделать это в этом простом сценарии?

Ответы [ 3 ]

39 голосов
/ 16 декабря 2010

Более одного потока, работающего в одном контексте Entity Framework, не является поточно-безопасным.

Отдельный экземпляр контекста для каждого потока является поточно-ориентированным.Пока каждый поток выполнения имеет свой собственный экземпляр контекста EF, у вас все будет хорошо.

В вашем примере вы можете вызывать этот код из любого числа потоков одновременно, и каждый будет счастливо работать со своим собственным контекстом.

Однако я бы предложил реализовать для этого блок 'using' следующим образом:

// this method is called from several threads concurrently
public void IncrementProperty()
{
   using (var context = new MyEntities())
   {
      context.SomeObject.SomeIntProperty++;
      context.SaveChanges();
   }
}
0 голосов
/ 29 ноября 2017

Вы можете использовать фабричный подход, чтобы внедрить ваш DbContext как фабрику, а не как отдельный экземпляр, посмотрите на это: https://github.com/vany0114/EF.DbContextFactory

Это безопаснее, и вы избегаете жесткого копирования создания экземпляра в свои репозитории.

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

Существует расширение для Ninject, которое делает это очень простым способом, просто вызывая метод kernel.AddDbContextFactory<YourContext>();, также вам нужно изменить свой репозиторий, получив Func<YourContext>

0 голосов
/ 16 декабря 2010

Я считаю, что SomeObject.SomeIntProperty является статическим.Это не имеет ничего общего с тем, что Entity безопасен для потоков.Если вы пишете в статические переменные в многопоточной среде, вы всегда должны заключать их в двойную проверку блокировки для обеспечения безопасности потока.

...