我有一个存储库类,它正在查询EF DbContext,如下所示:
public IEnumerable<ProductFilterData> GetAllProducts()
{
return this.DataContext.Products.Select(x => new ProductFilterData { Id = x.Id, Name = x.Name, ProductDetailLevelCode = x.ProductDetailLevel.Code, Description = x.Description, ParentProductIds = x.ParentProducts.Select(p => p.Id) });
}
哪个工作正常。但是,当我将此代码重构为:
public IEnumerable<ProductFilterData> GetAllProducts()
{
return this.MapToProductFilterData(this.DataContext.Products);
}
private IEnumerable<ProductFilterData> MapToProductFilterData(IEnumerable<Product> products)
{
return products.Select(x => new ProductFilterData { Id = x.Id, Name = x.Name, ProductDetailLevelCode = x.ProductDetailLevel.Code, Description = x.Description, ParentProductIds = x.ParentProducts.Select(p => p.Id) });
}
我得到一个例外:
已经有一个与此命令关联的开放DataReader 必须先关闭。
为什么将DbSet的引用传递给方法会导致EF的行为发生变化?顺便说一句,如果我将MapToProductFilterData的参数类型更改为IQueryable,那么它可以工作。此外,如果我删除关系映射,它也可以。
答案 0 :(得分:4)
您必须将其更改为IQueryable
,因为如果您将其作为IEnumerable
传递,则实际执行查询SELECT * FROM Product
。您的方法开始迭代结果集,但您的投影调用x.ParentProducts.Select(p => p.Id)
会导致延迟加载ParentProducts
导航属性。延迟加载会打开第二个活动数据阅读器,只有拥有它enabled in connection string才能使用。