将DbSet传递给参数类型为IEnumerable<>的方法时的奇怪EF行为

时间:2011-12-16 21:18:28

标签: c# entity-framework-4

我有一个存储库类,它正在查询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,那么它可以工作。此外,如果我删除关系映射,它也可以。

1 个答案:

答案 0 :(得分:4)

您必须将其更改为IQueryable,因为如果您将其作为IEnumerable传递,则实际执行查询SELECT * FROM Product。您的方法开始迭代结果集,但您的投影调用x.ParentProducts.Select(p => p.Id)会导致延迟加载ParentProducts导航属性。延迟加载会打开第二个活动数据阅读器,只有拥有它enabled in connection string才能使用。