Отслеживание параллелизма EF при сохранении изменений из другого потока - PullRequest
1 голос
/ 01 февраля 2012

У меня есть база данных, созданная с использованием кода EF.Работа с данными осуществляется с помощью DbContext.Контейнер IoC в приложении Asp.net генерирует экземпляр DbContext, на который объекты BL полагаются в расчете на поток.Это класс фоновых задач, который загружается вместе с веб-приложением.

Каждое время (например, каждые 10 минут) фоновый поток добавляет один элемент в список Incidents, вызывая * 1006.* в рамках транзакции.

Между тем, создается впечатление, что если один из Incidents изменяется на myDbContext в «потоке веб-запросов», даже если изменения на мгновение сохраняются в базе данных, они переопределяютсянабор Incidents, которые были извлечены фоновым потоком за несколько секунд до того, как пользователь использовал веб-страницу для изменения Incident.

Это похоже на проблему параллелизма (и я нереализовать любой параллелизм, такой как столбцы Timestamp).

Мой вопрос: разве фоновый поток не должен сохранять только измененные данные (в моем случае, добавляя новый инцидент), оставляя всю коллекцию инцидентов?Если это действительно так, мой источник проблемы находится где-то еще.

Код из фонового потока:

using (var transaction = new TransactionScope())
            {
                foreach (var scheduledTask in _db.ScheduledTasks)
                {
                    if (scheduledTask.NextExecuteAfterDate == null)
                    {
                        PopulateNextExecuteAfterDate(scheduledTask);
                        shouldSaveChanges = true;
                    }

                    if (DateTime.Now > scheduledTask.NextExecuteAfterDate)
                    {
                        RegisterRecurringTicket(scheduledTask);
                        CalculateNextTime(scheduledTask);
                        shouldSaveChanges = true;
                    }
                }

                if (shouldSaveChanges) _db.SaveChanges();
                transaction.Complete();
            }

Код в подпрограмме RegisterRecurringTicket(scheduledTask); добавляет элемент в коллекцию инцидентов.Когда вызывается _db.SaveChanges();, создается впечатление, что коллекция инцидентов перезаписывается более старым набором инцидентов, что приводит к тому, что сгенерированные пользовательским интерфейсом изменения в коллекции инцидентов устарели.Если да, как я могу решить эту проблему?

Ответы [ 2 ]

0 голосов
/ 03 февраля 2012

Проблема заключалась в том, что я использовал PerThreadScope DbContext инъекцию. Это привело к неожиданному поведению моего приложения ASP.NET. Настройка Ninject Module для разрешения DbContext в PerRequestScope устранила проблему.

0 голосов
/ 01 февраля 2012

Простой вызов myDbContext.Incidents.ToList() не приведет к перезаписи ничего в базе данных. Однако , я мог бы легко представить себе такую ​​ситуацию:

// My Incident tracker
IEnumerable<Incident> CurrentIncidents {get{return myDbContext.Incidents.ToList();}}

// Meanwhile, in another class on the same thread...
foreach(var incident in IncidentTracker.CurrentIncidents)
{
   var claims = myDbContext.Claims.Where(c => c.IncidentId == incident.IncidentId);
   foreach(var claim in claims)
   {
      Process(claim);
   }
   incident.Processed = true;
}
myDbContext.SaveChanges();

В приведенном выше примере, даже если вы не вытягиваете Incident s непосредственно из myDbContext,поскольку оба класса получили в них одинаковый контекст, вызов SaveChanges() на самом деле влияет как на утверждения (которые вы хотели изменить), так и на инциденты (которые вы не сделали).

Возможно ли, что-то вродеэто происходит?

...