I have an EF code-first generated database. Data manipulation is done using DbContext. An IoC container in Asp.net application generates a DbContext instance, that BL objects rely on on a per thread basis. The is a background task class that is loaded along with a web application.
Every one in a while (like every 10 minutes), a background thread adds one item to a list of Incidents by calling myDbContext.Add within a transaction scope.
Meanwhile, it seems like if one of the Incidents is changed by myDbContext in a “web requests thread”, even though the changes are saved to a database for a moment, they are getting overridden by the set of the Incidents, that were pulled by the backgound thread a few moments before the user used the web page to alter an Incident.
This seems like a concurrency problem (and I don’t implement any concurency like Timestamp columns).
My question is: Shouldn’t the background thread only save changed data (in my case, adding a new incident), leaving an entire incidents collection? If it is indeed true, my problem source is somewhere else.
Code from a background thread:
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();
}
The code in subroutine RegisterRecurringTicket(scheduledTask); adds item to an Incidents collection. When a _db.SaveChanges(); is called, it seems like the collection of incidents is overwritten with the older set of incidents, casting the UI-generated changes to an Incidents collection obsolete. If so, how can I solve this problem?
The problem was that I was using a
PerThreadScopeDbContextinjection. This has resulted in an unexpected behaviour of my ASP.NET application. Setting the Ninject Module to resolveDbContextinPerRequestScopefixed the problem.