Reputation: 10307
I have a repository class which is querying the EF DbContext like this:
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) });
}
Which works fine. However, when I refactor this code to this:
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) });
}
I get an exception:
There is already an open DataReader associated with this Command which must be closed first.
Why does passing a reference to the DbSet to a method cause a change in the behavior of EF? Incidentally, if I change the parameter type of MapToProductFilterData to IQueryable then it works. Also, if I remove the relationship mappings it also works.
Upvotes: 1
Views: 1016
Reputation: 364249
You must change it to IQueryable
because if you pass it as IEnumerable
you actually execute query SELECT * FROM Product
. Your method starts iterating the result set but your projection calls x.ParentProducts.Select(p => p.Id)
which results in lazy loading of ParentProducts
navigation property. Lazy loading opens second active data reader which is possible only if you have it enabled in connection string.
Upvotes: 4