调用另一个 repo 时出错 - '已经有一个打开的 DataReader 与此命令关联,必须先关闭'
Posted
技术标签:
【中文标题】调用另一个 repo 时出错 - \'已经有一个打开的 DataReader 与此命令关联,必须先关闭\'【英文标题】:Error when calling another repo - 'There is already an open DataReader associated with this Command which must be closed first'调用另一个 repo 时出错 - '已经有一个打开的 DataReader 与此命令关联,必须先关闭' 【发布时间】:2016-04-26 10:03:07 【问题描述】: public IQueryable<Application> GetAppById(Guid Id)
return Repository.Query().Where(c => c.Id == Id).Select(c => c.App)
我在上面得到了这段代码,但它似乎不能正确返回。如果我调用数据库中的另一个存储库,例如 Repository2.Query().Where(??code??)。我收到以下错误。
错误: “已经有一个打开的 DataReader 与此命令关联,必须先关闭。”
但是,当我将返回更改为 ICollection 时,它会正确响应。
public ICollection<Application> GetAppById(Guid Id)
return Repository.Query().Where(c => c.Id == Id).Select(c => c.App).ToList();
我调试 IQueryable 返回,没有错误但我找不到它检索的数据。当您调用另一个到 repo 时会发生错误。
【问题讨论】:
在此之前,您是否在程序中的其他任何地方打开了同一连接上的 DataReader(或调用任何执行此操作的代码)?您是否正在尝试使用来自多个线程的 DbContext? 我调试 IQueryable 返回,没有错误但我找不到它检索的数据。当您将另一个调用到 repo 时会发生错误。 我感觉区别不在于IQueryable
与ICollection
,而是您调用.ToList()
的事实,这将在现场全面评估您的惰性查询。 Repository.Query()
是你自己的代码,还是标准框架(例如EntityFramework))?
【参考方案1】:
消息是正确的;您已允许同时执行两个命令。显示的第一个方法返回一个“查询” - 它实际上不会执行 anything 直到你迭代它 - 并且在你 stop 迭代它之前是打开的。事实上,IQueryable<T>
的全部目的是在执行之前允许额外的组合。因此,假设您使用foreach
,查询在foreach
的持续时间内是活动的,不是调用GetAppById
本身。所以如果你做经典的“N+1”:
foreach(var row in SomeOuterQuery(...)) // N+1, not a great idea
SomeInnerQuery(row, ...);
那么你绝对是在同时运行多个命令。
有三个主要修复:
完整运行第一个查询,然后迭代结果 - 这就是添加ToList
所做的:它将foreach
移动到内部 GetAppById
启用“MARS”(多个活动结果集)-注意:这不是建议,只是“这将起作用”(但:并非所有起作用的都是好主意)
重组工作以不再需要“N+1”中的“N”,例如通过与外部列表同时获取附加数据(来自单个的多个结果网格例如查询)
【讨论】:
太棒了..这真的很有帮助.. ty以上是关于调用另一个 repo 时出错 - '已经有一个打开的 DataReader 与此命令关联,必须先关闭'的主要内容,如果未能解决你的问题,请参考以下文章
尝试插入、更新或删除时出错:已经有一个打开的 DataReader 与此命令关联,必须先关闭
使用hg convert将git repo转换为mercurial时出错
从另一个存储过程调用 sp_addextendedproperty 时出错
从另一个模块调用Worksheet_FollowHyperlink()时出错
Jersey REST 服务调用另一个 Jersey REST 服务时出错 - java.lang.IllegalArgumentException:参数类型不匹配