Подтвердить что ты не робот

Безопасность платформы Entity Framework

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

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

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

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

Я считаю, что сущность framework context реализует какую-то переменную 'counter', которая отслеживает, являются ли текущие значения в контексте свежими или нет.

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

Ответ 1

Более того, один поток, работающий в одном контексте 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();
   }
}

Ответ 2

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

Ответ 3

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

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

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

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