2012-12-11 41 views
1

只要我不使用註釋掉的using語句,以下代碼就可以工作。當我使用using我得到The operation cannot be completed because the DbContext has been disposed使用聲明和實體框架

public IQueryable<DTOs.FormQuestionDTO> GetForm(int id, int page = 0) 
{ 
    // FS stores pages starting with 1 
    page = page == 0 ? 1 : page; 

    //using (var db = new Models.FormEntities()) 
    //{ 
     var db = new Models.FormEntities(); 

     var questions = from fq in db.FormQuestions 
         join q in db.Questions on fq.QuestionId equals q.QuestionId 
         where (fq.FormId == id) && (fq.PageNumber == page) && fq.Disabled == false 
         orderby fq.DisplayOrder 
         select new { q.QuestionId, q.QuestionText, fq.DisplayOrder, fq.PageNumber }; 

     var dto = questions.Project().To<DTOs.FormQuestionDTO>(); 

     if (questions == null) 
     { 
      throw new HttpResponseException(HttpStatusCode.NotFound); 
     } 
     else 
     { 
      return dto; 
     } 
    //} 
} 

我最初的直覺是,在使用LINQ查詢後立即處置的DbContext的,但把.Dipose()一個finally塊的內部時,我得到了同樣的錯誤。

這是怎麼回事?我沒有在C#中工作過一段時間,所以我可能錯過了一些簡單的東西。

+0

什麼是堆棧跟蹤? – SLaks

回答

5

實體框架LINQ提供程序使用deferred execution。這意味着直到迭代IQueryable爲止,查詢纔會在數據庫上執行。

發生什麼事情是,在處理上下文後,某些東西會迭代您的查詢,從而導致它嘗試執行數據庫查詢。

您可以通過調用ToList()立即強制執行它。

var dto = questions.Project().To<DTOs.FormQuestionDTO>().ToList(); 
+0

謝謝,那是它。有沒有一種等效的方法可以導致執行,但返回IQueryable類型的集合?或者我必須將返回的列表轉換回IQueryable? – Jelling

+0

不是我沒有。我傾向於將IQueryable視爲未執行的查詢,所以我認爲它適合。其他將執行IQueryable查詢的方法有['ToArray','ToDictionary'](http://msdn.microsoft.com/zh-cn/library/bb341635.aspx)等。 – jrummell

0

+1 ti @ jrummell。 原因你得到的錯誤是,當在using中聲明的變量離開該範圍時,將在其上釋放DbContext的.Dispose()被調用。

如果你嘗試執行,DbContext不再存在。

+0

您確定適用於此處嗎?原始代碼仍在使用{}的上下文中;看起來更像是DbContext由於延遲執行而尚未創建。 – Jelling

+1

@Jelling:他返回IQueryable,所以可能會在* using *語句的上下文之外迭代它。 –