2016-01-15 35 views
1

我想在我的ASP.NET MVC控制器中使用async/await模式。我越來越在MVC控制器,希望異步返回EntityFramework CodeFirst數據

的ObjectContext的實例已設置,並且可以不再

最終使用的錯誤,我想我的緩存結果,但現在我認爲第一步是剛剛弄清楚如何與EF工作和異步回/等待

public class SpeakerController : Controller 
    { 
     public async Task<ActionResult> Index() 
     { 
      using (var context = new MultiTenantContext()) 
      { 
       var speakersAll = await context.Speakers.ToListAsync(); 
       return View("Index", speakersAll); 
      } 
     } 

發現的解決方案:

private MultiTenantContext context = new MultiTenantContext(); 

    public async Task<ActionResult> Index() 
    { 
      var speakersAll = await context.Speakers.ToListAsync(); 
      return View("Index", speakersAll); 
    } 

正如我在下面的評論中所說的,將上下文從使用中拉出,會導致在ToListAsync()實際執行時不會處理它。

+0

哪一行發生錯誤? – Carl

+0

我剛剛找到一個例子,說明我可以將上下文移動到控制器中,如下所示:private MultiTenantContext context = new MultiTenantContext();這解決了這個問題。現在,我正在處理緩存問題 –

+2

您應該發佈解決問題的方法,作爲將來可能會遇到您的帖子的任何人的答案。 – drneel

回答

3

您應該避免使用Web應用程序中延遲加載,因爲我們的目標是儘量減少HTTP請求的響應時間,這最好通過減少數據庫請求來實現。特別是在MVC和/或Web API中,您擁有非常精細的操作方法,因此在大多數情況下應該可以準確確定您的數據要求,並將其包含在一個或幾個請求/查詢中。這會減少數據庫服務器的負載,併爲您的Web請求帶來更好的性能。

至於使用語句和dbcontexts,你不應該在你的控制器中實例化dbcontexts,如果你可以幫助它的話。注入它們會更好,並讓容器決定如何管理它們的壽命。通常情況下,每個請求只需要一個dbcontext實例,在請求的生命週期中,這些實例可用於所有需要EF的查詢(但很少可能)。如果您在使用StructureMap(我的偏好),你將與實現這一目標:

For<DbContext>.HybridHttpOrThreadLocalScoped().Use<MyContext>(); 

(請注意,這句法與StructureMap 4更新)

如果你不知道你是否信任我的建議,考慮到EF7正在進一步採納這一建議,並且使得使用依賴注入的EF7和MVC 6 而不使用很困難,以努力推動開發人員做正確的事情(落入「成功之坑」,因爲它是)。有關示例,請參閱官方asp.net文檔中的EF7/MVC6教程(http://docs.asp.net/projects/mvc/en/latest/tutorials/mvc-with-entity-framework.html)。

摘錄

請注意,我們不設置記錄器和BookContext任何價值。 依賴注入(DI)子系統在運行時自動設置這些屬性。 DI也處理對象的生命週期,所以你不需要調用Dispose。有關更多信息,請參閱依賴關係 注入。

+0

已經爲此+1了,但也想用此+1加入。 –

+0

感謝@ssmith關於異步或緩存的任何意見? –

+0

我是兩者的粉絲。異步我認爲你有。您可以使用[OutputCache]屬性(用於完整輸出)或通過CachedRepository(http://ardalis.com/building-a-cachedrepository-via-strategy-pattern)對數據進行緩存。 – ssmith

1

如果你懶惰加載Speaker.Sessions,你的上下文早在它被使用的時候就消失了,因此這個問題。

試試這個:

await context.Speakers.Include(x => x.Sessions).ToListAsync(); 

,以確保您的上下文超出範圍之前會話被加載。

可以使用不同的模式;例如使Context更長壽,但我個人認爲using()塊中的非常短暫的上下文是最好的,如果你不需要某種工作單元模式。

雖然這不是這裏的問題 - 你也應該不會混用延遲加載異步等待在EF:Why Does Await Not Appear to Prevent Second Operation on EF Context

+0

向列表添加「虛擬」關鍵字是否與.Include做同樣的事情?也就是說,揚聲器被定義爲虛擬列表(不僅僅是列表) –

+0

不是真的;他們更加貼心。作爲一般規則,虛擬允許EF延遲加載該屬性,並且包含要求它在其包含定義中加載否則延遲加載的屬性。 http://stackoverflow.com/questions/15247614/understanding-code-first-virtual-properties很好地解釋了虛擬部分。 – sellotape