编辑:原始文件假定错误发生在特定的地方,但似乎不是。我很感激有关如何追踪数据阅读器打开位置的任何建议 - 通过EF追踪它的一些方法是理想的,因为我还没有找到任何有效的方法。
我遇到了Entity Framework的问题,这给我带来了开放的数据读取错误,我不确定原因。
我为我的应用程序的中间层实现了一个通用基础存储库类。旧版本使用返回基类的通用“FindAll()”方法,然后我们依靠延迟加载来填充业务逻辑中的关系。由于这不如预期加载那么好,我们添加了一堆“FindByEager”方法,这些方法直接访问DbSet并使用.Include(t => t.propertyName)
来获取稍后需要的预先加载属性。
受this article的启发(参见“创建通用存储库”标题下),作为更大的重构的一部分,我正在尝试实现一个更通用的“FindAll”方法,该方法可以使用动态添加包含方法DbExtensions.Include(IQueryable, String)。我的基础存储库中生成的代码如下所示:
public virtual IQueryable<T> FindAll(string includeProperties = "")
{
var query = NcContext.Set<T>().AsQueryable();
foreach (var property in includeProperties.Split
(new char[] {','}, StringSplitOptions.RemoveEmptyEntries))
{
query = query.Include(property);
}
return query;
}
然而,实体框架并不喜欢这个。当我尝试迭代包含属性字符串和.Include
每个属性时,EF希望将其视为对打开的DataReader的操作(旧的错误“已经存在与此连接关联的打开的DataReader,必须首先关闭“每当我们尝试执行结果查询时出现。”
我尝试过跟踪堆栈跟踪并修改其他一些方法,以确保我之前使用的每个连接都使用.ToList()
执行。我看不到其他地方可能有数据阅读器打开。
我正在调试器中逐步执行此方法。传递var query = ...
行后,我可以成功枚举查询并获得结果。一旦我走过.Include()
之一(即通过foreach循环),如果我尝试枚举查询,我就会遇到问题。
我有兴趣了解为什么会发生这种情况(没有找到很多关于此的文档的运气)以及如何解决它。它也打破了我对Entity如何工作的理解,因为它不应该延迟执行构建的查询直到实际的评估时间?
传递表达式而不是字符串&amp;使用其他DbExtensions.Include<T, TProperty> (IQueryable<T>, Expression<Func<T, TProperty>>)
重载。无论这是否是解决方案,我想了解为什么实体会产生这种行为。
使用.ToList()
将DbSet拉入内存。我试图允许消费类至少有一点可重用性来微调他们正在运行的查询,所以我想返回一个Queryable
,并强制执行查询然后重新转换为Queryable似乎不效率很高。
无论这些是否会修复它(如果它们会更新),我会有兴趣知道我在这里做错了什么以及它为什么会这样。
感谢您的帮助。