2015-11-04 86 views
1

我想通過一系列危險來查看是否已在ControlMeasures中爲每個危險添加了控制措施。 如果每個危險都有一個控制措施,那麼我將complete設置爲true,否則我會中斷foreach循環,將complete set設置爲false。已經有一個打開的DataReader與此命令相關聯,必須先關閉 - Foreach循環,如果語句

我已經寫了下面的foreach循環,但在運行時我得到顯示了針對if條件語句以下錯誤:

已經有一個用此命令,必須先關閉相關聯的打開的DataReader。

我已經做了一些研究,看來我沒有以正確的方式編寫代碼,但由於我仍然對此不熟悉,所以無法找到一種更好,更正確的編寫方式。

[HttpGet] 
    public ViewResult AddControlMeasure(int raId) 
    { 
     // Get list of hazardids for this RA 
     IEnumerable<int> hazardIds = db.RiskAssessmentHazards.Where(x => x.RiskAssessmentId == raId).Select(x => x.HazardId); 

     var complete = false; 
     foreach (int HazardsId in hazardIds) 
     { 
      if (db.ControlMeasures.Where(x => x.HazardId == HazardsId && x.RiskAssessmentId == raId).Count() == 0) 
      { 
       break; 
      } 
      else 
      { 
       complete = true; 
      } 
     } 
+0

我認爲你需要添加一個'.ToList'或'.ToArray'你'hazardIds'選擇的結尾,否則在完成整個枚舉之前,不會關閉該讀者的連接。我也確信有一種方法可以在沒有for循環的情況下進行,但我現在正在畫一個空白。 –

+0

可能是因爲'db.RiskAssessmentHazards'返回'IQueryable',所以在執行foreach循環時並沒有真正執行。 – markpsmith

回答

3

這條線:

IEnumerable<int> hazardIds = db.RiskAssessmentHazards 
    .Where(x => x.RiskAssessmentId == raId).Select(x => x.HazardId); 

返回一個懶惰的評估程序(真正的IQueryable,直到你開始枚舉(該foreach)不會打數據庫

循環:

foreach (int HazardsId in hazardIds) 
{ 
    ... 
} 

將打開與數據庫的連接e,找到讀者,並在每次迭代中沿着讀者移動以獲取數據。這意味着連接在您的循環期間有一個活動的閱讀器。

最後,這條線:

if (db.ControlMeasures.Where(x => x.HazardId == HazardsId && x.RiskAssessmentId == raId).Count() == 0) 

嘗試使用的連接(與您db相關)執行另一個查詢。由於foreach循環可查詢,您已擁有活動閱讀器,因此會引入您收到的錯誤。

儘管它通常是一個壞主意,在循環中執行查詢,最簡單的解決辦法是讓你使用.ToArray()或其他方式來迭代循環之前完全實現的結果:

int[] hazardIds = db.RiskAssessmentHazards 
    .Where(x => x.RiskAssessmentId == raId) 
    .Select(x => x.HazardId) 
    .ToArray(); 

這樣,在開始迭代循環並執行後續查詢之前,讀者將被關閉。

+0

非常感謝您的一個很好的答案,我很好的學習了很多,並修復了問題 –

2

Where, Select,GroupByOrderBy等方法使用延遲執行(這會導致打開DataReader就像你的情況)。這些方法不會強制查詢執行,因此查詢執行被推遲到枚舉。因此,您應該使用ToList()ToArray()來進行枚舉。

在你的情況,你應該強制枚舉`hazardIds'像

IEnumerable<int> hazardIds = db.RiskAssessmentHazards 
          .Where(x => x.RiskAssessmentId == raId) 
          .Select(x => x.HazardId).ToArray(); 
+0

@BasharAbuShamaa沒有問題。很高興它有幫助。) – user2771704

相關問題