实体框架:已经有一个与此命令关联的开放DataReader,必须先关闭它

时间:2011-10-28 10:19:46

标签: asp.net-mvc asp.net-mvc-3 entity-framework entity-framework-4 entity-framework-4.1

此问题与this

有关

我的存储库方法有以下代码:

 public IEnumerable<ApplicationPositionHistory> GetApplicationPositionHistories(int applicantId, int positionId)
        {
            return context.ApplicationsPositionHistory.Where(d => d.applicantPosition.ApplicantID == applicantId && d.applicantPosition.PositionID == positionId).Include(o => o.applicantPosition) ;
        }

我的Html有这段代码:

@foreach (var item in Model) {
    <tr>
        <td>
            @Html.DisplayFor(modelItem => item.applicantPosition.Applicant.name)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.applicantPosition.Position.name)
        </td>

完整的例外是:

已经有一个与此命令关联的打开DataReader,必须先关闭它。

它是HTML的第一行   @ Html.DisplayFor(modelItem =&gt; item.applicantPosition.Applicant.name)

5 个答案:

答案 0 :(得分:22)

快速解决方案:

public IEnumerable<ApplicationPositionHistory> GetApplicationPositionHistories(int applicantId, int positionId)
    {
        return context.ApplicationsPositionHistory.Where(d => d.applicantPosition.ApplicantID == applicantId && d.applicantPosition.PositionID == positionId).Include(o => o.applicantPosition).ToList() ;
    }

如果您想知道,为什么要解决您的问题,请阅读LINQ和违反执行的工作原理。简而言之 - 如果你不通过ToList“枚举”查询来“强制”执行select,那么它实际上执行得太晚了 - 在视图中。这会导致其他想要使用相同连接的查询出现问题。

答案 1 :(得分:12)

您是否尝试将MultipleActiveResultSets=true;添加到连接字符串?

答案 2 :(得分:6)

当您在另一个查询中执行新查询时,会发生此错误。考虑一下你在视图中有这样的东西

@Html.DisplayFor(modelItem => item.Device.Name)

并在您的设备型号中

    public string Name
    {
        get
        {
            return String.Format("{0} {1}", Brand.BrandName, Model.ModelName);
        }
    }

然后,为了评估Device.Name,它需要查询其品牌和模型,它将成为查询内部的查询,因此解决方案是在数据库连接字符串中启用MutlipleActiveResultSets,如下所示:

    <add name="MyDBContext" connectionString="Data Source=.;Initial Catalog=mydb;Integrated Security=True;MultipleActiveResultSets=True" providerName="System.Data.SqlClient" />

答案 3 :(得分:1)

通常不要在视图中使用EF对象,而是为视图模型创建POCO对象并将查询结果映射到视图模型上。 EF不会在存储库方法中执行查询,因为查询不是在定义时执行,而是仅在您尝试访问数据时执行。在您的视图中,您多次使用相同的查询,这是不正确的。

如果要访问存储库方法返回的对象列表,请使用toList

答案 4 :(得分:0)

如果您在查询结束此执行之前从ApplicantPosition实体加载位置引用,则会出现真正的问题。如果您想在该场景中保留延迟执行,您可以急切地在查询中加载位置参考,如下所示:

包含(o =&gt; o.applicantPosition.Select(a =&gt; a.Position));

并在您的GetApplicationPositionHistories上继续返回IEnumerable。

另一个解决方案是在GetApplicationPositionHistories方法上实际运行查询,调用查询上的ToList()或ToArrray()方法。