我有一个EF代码优先生成的数据库。使用DbContext
完成数据操作。 Asp.net应用程序中的IoC容器生成DbContext
实例,BL对象依赖于每个线程。这是一个后台任务类,它与Web应用程序一起加载。
每隔一段时间(每10分钟一次),后台线程通过在事务范围内调用Incidents
将一个项添加到myDbContext.Add
列表中。
与此同时,似乎Incidents
中的一个myDbContext
在“Web请求线程”中被Incidents
更改,即使更改被保存到数据库片刻,它们也会被覆盖在用户使用网页改变Incident
之前的几分钟,由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();
}
的集合提取。
这似乎是一个并发问题(我没有像Timestamp列那样实现任何可靠性。)
我的问题是:后台线程不应该只保存更改的数据(在我的情况下,添加新事件),留下整个事件集合吗?如果确实如此,我的问题来源就是其他地方。
后台线程中的代码:
RegisterRecurringTicket(scheduledTask);
子例程_db.SaveChanges();
中的代码将项添加到事件集合中。当调用{{1}}时,似乎事件集合被旧的事件集覆盖,将UI生成的更改转换为过时的事件集合。如果是这样,我该如何解决这个问题?
答案 0 :(得分:0)
简单地调用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
提取myDbContext
,因为两个类都注入了相同的上下文,因此调用SaveChanges()
实际上会影响{{1}}声明(您想要更改)和事件(您没有更改)。
这样的事情有可能发生吗?
答案 1 :(得分:0)
问题在于我正在使用PerThreadScope
DbContext
注射。这导致我的ASP.NET应用程序出现意外行为。设置Ninject模块以解决DbContext
中的PerRequestScope
问题。