2012-01-31 54 views
1

我有一个EF代码优先生成的数据库。数据处理使用DbContext完成。 Asp.net应用程序中的IoC容器生成一个DbContext实例,即BL对象依赖于每个线程。这是一个随Web应用程序一起加载的后台任务类。从不同线程保存更改时的EF协议跟踪

每隔一段时间(如每隔10分钟),后台线程通过在事务范围内调用myDbContext.Add将一个项目添加到Incidents列表中。

同时,好像如果Incidents之一是myDbContext在“Web请求的线程”改变,即使改变被保存到了片刻的数据库,它们越来越被集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();时,看起来事件的集合被旧集合覆盖,将用户界面生成的更改投弃置于事件集合。如果是这样,我该如何解决这个问题?

回答

0

问题是我正在使用PerThreadScopeDbContext进样。这导致了我的ASP.NET应用程序的意外行为。设置Ninject模块,以解决中的DbContext问题。

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()实际上影响(您想要改变的)索赔和事件(您没有)。

是否有可能发生这样的事情?

+0

是的。自从我发现,我已经更新了问题主体,我误导了问题读者关于问题设置。请看一下。 – 2012-01-31 23:26:05