Считывается зафиксированный снимок с EF Savechanges, вызывающий состояние гонки - PullRequest
0 голосов
/ 30 октября 2018

У меня проблема с EF6, использующим подход Code-First, когда новый контекст БД, пытающийся получить доступ к объекту, вызывает исключение нулевой ссылки. Вот пример моего сценария:

Основная нить

int personId = 0;
using(var ctx = new exampleContext())
{
  var person = new Person() {Name = "Alex"};
  ctx.People.Add(person);
  ctx.SaveChanges();
  personId = person.id;
}

Task.Run(() => {someOtherThread(personId)})

Другая тема

public static someOtherThread(int personId)
{
     using(var ctx = new exampleContext())
     {
        var person = ctx.People.Where(x => x.id == personId);
        //Exception here.
        var name = person.Name;
     }
}

Когда я отключаю опцию Is Read Committed Snapshot в БД, это работает как положено (по умолчанию, когда EF создает БД), но мы хотим поддерживать максимально оптимистичную модель управления параллелизмом.

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

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

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

Спасибо!

1 Ответ

0 голосов
/ 30 октября 2018

возвращает ноль, потому что .Add не записывает изменения в db, поэтому сначала вам нужно SaveChanges(), затем вы сможете достичь идентификатора нового персонажа так, как вы пытаетесь.

 var person = new Person() {Name = "Alex"};
      ctx.People.Add(person);
      personId = person.id;

в коде должно быть

var person = new Person() {Name="Alex"};
ctx.People.Add(person);
ctx.SaveChanges();
personId=person.id;

также, если вы установите точку останова на personId, вы увидите значение, возвращающееся 0, пока вы не вызовете SaveChanges()

...