asp.net-mvc 实体框架:已经有一个与此命令关联的打开的 DataReader 必须先关闭
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7927990/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Entity Framework: There is already an open DataReader associated with this Command which must be closed first
提问by Luis Valencia
This question is related to this:
这个问题与此有关:
My repository method has this code:
我的存储库方法具有以下代码:
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) ;
}
My Html has this code:
我的 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>
The full exception is:
完整的例外是:
There is already an open DataReader associated with this Command which must be closed first.
已经有一个与此命令关联的打开的 DataReader,必须先关闭它。
It was throw in the first line of the HTML @Html.DisplayFor(modelItem => item.applicantPosition.Applicant.name)
它被扔在 HTML @Html.DisplayFor(modelItem => item.applicantPosition.Applicant.name) 的第一行
回答by rouen
Quick solution :
快速解决方案:
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() ;
}
If you want to know, why this fixing your problem, read about how LINQ and deffered executionworks. In few words - if you dont "force" execution of the select by "enumerating" query by ToList, it is in fact executed too late - in view. And this is causing trouble with other queries which want to use same connection.
如果您想知道为什么这可以解决您的问题,请阅读 LINQ 和延迟执行的工作原理。简而言之 - 如果您不通过 ToList 的“枚举”查询“强制”执行选择,实际上它执行得太晚了 - 在视图中。这给想要使用相同连接的其他查询带来了麻烦。
回答by hofnarwillie
Have you tried adding MultipleActiveResultSets=true;to your connection string?
您是否尝试添加MultipleActiveResultSets=true;到您的连接字符串?
回答by Mohsen Afshin
This error happens when a new query is going to be executed while you're in inside another query. Consider you have something like this in your view
当您在另一个查询中时要执行新查询时,会发生此错误。考虑你有这样的事情在你看来
@Html.DisplayFor(modelItem => item.Device.Name)
and in your Device model you have
在你的设备模型中你有
public string Name
{
get
{
return String.Format("{0} {1}", Brand.BrandName, Model.ModelName);
}
}
then since for evaluating Device.Name it requires to query its Brand and Model it will become query inside query and so the solution is to enable MutlipleActiveResultSetsin your database connection string as follows:
然后因为为了评估 Device.Name 它需要查询它的 Brand 和 Model 它将成为查询内的查询,所以解决方案是在你的数据库连接字符串中启用MutlipleActiveResultSets,如下所示:
<add name="MyDBContext" connectionString="Data Source=.;Initial Catalog=mydb;Integrated Security=True;MultipleActiveResultSets=True" providerName="System.Data.SqlClient" />
回答by Max Zerbini
Generally do not use EF object in view, but create a POCO object for the view model and map the query result on the view model. EF do not execute the query in your repository method because the query are not executed at definition time but only when you try to access the data. In your view you are using the same query many time and this is not correct.
一般不会在视图中使用EF对象,而是为视图模型创建一个POCO对象,并将查询结果映射到视图模型上。EF 不会在您的存储库方法中执行查询,因为查询不会在定义时执行,而只会在您尝试访问数据时执行。在您看来,您多次使用相同的查询,这是不正确的。
If you want to access the list of object returned by your repository method, use toList
如果要访问存储库方法返回的对象列表,请使用 toList
回答by marianosz
The real problem if that you are Lazy Loading the Position reference from the ApplicantPosition entity before the query ends this execution. If you want to keep the deferred execution on that scenario you can eager load the Position reference on your query like this:
如果您在查询结束此执行之前延迟加载来自 ApplicantPosition 实体的 Position 引用,那么真正的问题是。如果您想在该场景中保留延迟执行,您可以像这样在查询中预先加载 Position 引用:
Include(o => o.applicantPosition.Select(a => a.Position));
Include(o => o.applicantPosition.Select(a => a.Position));
and on your GetApplicationPositionHistories keeps returning the IEnumerable.
并在您的 GetApplicationPositionHistory 上不断返回 IEnumerable。
The other solution is to actually run the query on the GetApplicationPositionHistories method calling the ToList() or ToArrray() methods on the query.
另一种解决方案是在 GetApplicationPositionHistories 方法上实际运行查询,在查询上调用 ToList() 或 ToArrray() 方法。

