2014-04-21 33 views
1

我有一個相當大的查詢,我想在多個線程中執行以最大化性能。這裏是我的代碼的概括:實體框架上下文中的多線程

public ActionResult ControllerAction() 
{ 
    using(var context = new DataEntities()) 
    { 
     var person = context.People.First(p => p.UserId == User.Identity.UserId); 
     var model = new PersonViewModel(person); 
     return View(model); 
    } 
} 

// Inside the PersonViewModel class 

public List<ApplicationViewModel> Applications { get; set; } 
public List<MessageViewModel> Messages { get; set; } 

public PersonViewModel(Person person) 
{ 
    var applicationsThread = new Thread(PopulateApplications); 
    applicationThread.Start(person); 
    var messagesThread = new Thread(PopulateMessages); 
    messagesThread.Start(person); 
    // Other code to be done while application/messages threads run 
    applicationThread.Join(); 
    messagesThread.Join(); 
} 

private void PopulateApplications(object personObject) 
{ 
    var person = personObject as Person; 
    Applications = person.Applications.Where(/*logic*/); 
} 

private void PopulateMessages(object personObject) 
{ 
    var person = personObject as Person; 
    Messages = person.Messages.Where(/*logic*/); 
} 

但是,當我點擊該控制器操作時,只有應用程序被填充。我猜這與嘗試從多個線程訪問實體上下文對象的屬性有關,但這些線程都不應該彼此衝突。切換線程順序導致消息被填充但應用程序將保持未填充的事實加強了該假設。

編輯,下面是一個使用krillgar的回答更新版本:

private static async void GenerateAbilities(int personId) 
{ 
using (var context = new BattleGameEntities()) 
{ 
    var personAbilities = await context 
     .persons 
     .First(p => p.personId == personId) 
     .Messages 
     .OrderBy(m => m.Date).Select(a => new MessageViewModel 
     { 
      //Logic 
     }).ToListAsync(); 
} 

}

回答

1

正確的。造成這種情況的根本原因是DbContext在DataReader上運行。其中只有一個可以一次打開。

如果您使用的是.NET 4.5和EF 6,那麼您可以使用新的Async()方法爲所有這些方法自動使用多個線程。基本上它只是任何方法的後綴。 Here是關於使用這些新方法的文章。

var applications = context.Applications.ToListAsync(); 
var messages = context.Messages.ToListAsync(); 

如果您使用的是.NET 4.0,那麼您必須在每個線程中創建一個新的上下文,並分別進行維護。此時,您還會遇到對象來自不同上下文的問題。

是的,我知道文章是在VB.NET中,但語法是類似的。無論出於何種原因,這就是他們寫的所有文章。

+3

請注意,從EF 6開始,單個上下文只能有一個併發的異步操作。異步不會爲您提供多個線程,它使您獲得響應能力。您需要多個上下文實例才能進行多個併發讀取。 –

+0

我正在使用EF6.0,並針對4.5框架(NuGet確認我有最新版本的EF引用了有問題的項目),但我沒有看到暴露的'ToListAsync()'方法。我會更新我的帖子以表明發生了什麼。 – jokulmorder

+0

@AdamHouldsworth我不知道。謝謝。我還沒有使用過,因爲我們仍在使用VS2010。 – krillgar