2014-05-09 54 views
0

我開始一個新項目,希望利用.NET中的異步/等待項目以及實體框架(版本6.1)中的新異步操作。然而,我很好奇的是如何重構我的應用程序的某些部分以減少代碼重複以及在給定EF的非線程安全特性的情況下完成此操作的最佳方式。使用實體框架和重構異步/等待問題

例子,我有我的業務層的一些方法,看起來像這樣

public async Task<MyViewModel> GetProgramIndexAsync(long programId){ 
      using (var db = new DbEntities()) 
      { 
       var program = await db.Programs.FirstOrDefaultAsync(x => x.Id == programId && x.Active); 
       if (program == null) 
       { 
        throw new ApplicationException("Cannot find the requested program"); 
       } 
      //more code to populate the view model 
      } 
     } 

到目前爲止,一切都很好。但我發現自己在這個服務層的多個地方進行檢查。什麼是理想的做法是提取到一個單獨的功能

private async Task<Program> GetProgramAsync(long programId){ 
      using (var db = new DbEntities()) 
      { 
       var program = await db.Programs.FirstOrDefaultAsync(x => x.Id == programId && x.Active); 
       if (program == null) 
       { 
        throw new ApplicationException("Cannot find the requested program"); 
       } 
      return program; 
      } 
     } 

現在,我的公共服務層調用只需調用這個函數,而不必重複此每次檢查。

var program = await GetProgramAsync(programId); 

我擔心的是爲這些請求中的每一個請求啓用多個上下文。在過去的(同步),我可以簡單地具有第二功能參數如

private async Task<Program> GetProgramAsync(long programId, DbContext db){ 

和現存上下文傳遞到方法。不過,我認爲這會對異步/等待性質造成影響。

我在想這個(多語境並不差)還是有更好的方法來完成這個?我應該注意到這些調用是隻讀的,我不會以這種方式更新實體。

回答

2

您認爲自己遇到的問題都不是問題。

  1. 由於連接池的原因,旋轉多個上下文並不是一個真正的問題。創建一個新的上下文實際上並不需要創建一個新的數據庫連接,它只是從池中獲取一個。如果您在即將需要一個新的連接之前將一個連接放回池中,而不是連接很多併發的連接,則這個連接的開銷很小。

  2. 如果你確實傳遞這些方法之間的上下文,它的仍然沒有問題。代碼是異步的,但它並沒有做任何事情。上下文一次只能由單個線程使用。你總是在等待任何可能是異步的操作,這意味着儘管與這些方法完全相關的其他代碼可能正在使用CPU,無論這是另一個響應處理程序(如果這是ASP),UI還會抽取其他事件(如果這是一個桌面應用程序)或其他東西,你仍然沒有處於從多個線程立即訪問的位置。

+0

謝謝!我想我可能會略微誤解異步的工作流程及其對EF的影響,但不希望只是爲了不必重構所有內容。 – Tommy