2014年1月30日 星期四

ASP.NET MVC 4 WebApi 遇到 「 已經開啟一個與這個 Command 相關的 DataReader,必須先將它關閉。」的解決方案

今天在寫 ASP.NET MVC 4 WebApi 撰寫 Controller 時,遇到以下錯誤:


已經開啟一個與這個 Command 相關的 DataReader,必須先將它關閉。

程式碼如下:
IEnumerable<BASE_Field> base_field = db.BASE_Field.Include(x => x.FieldLanguage).AsEnumerable();
IEnumerable<COMP_FieldSetting> comp_fieldsetting = db.COMP_FieldSetting.Include(x => x.Field).Include(x => x.FieldSettingLanguage).Where(x => x.Company.CompanyId == companyid).AsEnumerable();

BASE_Field 關聯 COMP_FieldSetting 為一對多的關係,我本想撈出 BASE_Field 所有資料再將 COMP_FieldSetting 資料塞進去,所以將兩份完整資料先撈出來再做處理,以減少對資料庫下指令的次數。

但是如果再用 COMP_FieldSetting 去做 Where 指令:
foreach ( BASE_Field _field in base_field )
{
    _field.FieldSetting = comp_fieldsetting.Where(x => x.Field.FieldId == _field.FieldId);
}

就會發生錯誤,原因是「Entity Framework 內部是使用 DataReader 作資料存取,所以如果呼叫 where,就會發生錯誤」

解決方法有二:

1. 設定 ConnectionString 加上 MultipleActiveResultSets = true,但只適用於SQL 2005以後之版本。 ( 此方法我沒試過 )
2. 先讀出放置在 List 中,所以程式碼改調整為:

List<BASE_Field> base_field = db.BASE_Field.Include(x => x.FieldLanguage).ToList();
List<COMP_FieldSetting> comp_fieldsetting = db.COMP_FieldSetting.Include(x => x.Field).Include(x => x.FieldSettingLanguage).Where(x => x.Company.CompanyId == companyid).ToList();

使用 List 就是他會將資料內容轉換為獨立實體物件,而不再跟 DataReader 有關。

引用:“已有打开的与此 Command 相关联的 DataReader,必须首先将它关闭。”解决方法



沒有留言 :

張貼留言

Related Posts Plugin for WordPress, Blogger...