28

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

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

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

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

Я считаю, что основа сущности контекст реализует какое-то переменный «счетчик», который отслеживает ли текущие значения в контексте свежие или нет.

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

* "Контекст объектов генерируется Entity Framework не являются потокобезопасными. * * - почему вы так говорите? – RPM1984 2010-12-15 22:42:31

+0

Я имею в виду MSDN: http://msdn.microsoft.com/en-us/library/system.data.objects.objectcontext.aspx, где говорится: «Класс ObjectContext не является потокобезопасным». – Harper 2010-12-15 22:49:57

ответ

31

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

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

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

Однако, я хотел бы предложить реализацию «используя» блок для этого следующим образом:

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

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

0

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

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

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

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