The problem I faced was getting the model class that was scaffolded with the "-Repository" option to work in harmony with MySQL Connector. After making all the required changes to bring the compilation to succeed, I opened the page only to see the error, "There is already an open DataReader associated with this Connection which must be closed first." on the line that tried to access the model's associated collection:
// Connection opens, the page queries something.
<td>
@item.ProductName
</td>
<td>
@(item.products == null ? "None" : item.products.Count.ToString()) // Connection still opens, the page queries again. BAM! Exception!
</td>
I googled through various threads to find out that:
- The Entity Framework uses Lazy Loading and
- When the collection was called, the server tried to query second data set using the same connection.
The method,
public ViewResult Index()
{
return View(productRepository.All);
}
It calls the public interface IproductRepository : IDisposable
{
IQueryable<product> All { get; }
IQueryable<product> AllIncluding(params Expression<Func<product, object>>[] includeProperties);
product Find(string id);
void InsertOrUpdate(product product);
void Delete(string id);
void Save();
}
public class productRepository : IproductRepository
{
dbEntities context = new dbEntities();
public IQueryable<product> All
{
get { return context.products; }
}
public IQueryable<product> AllIncluding(params Expression<Func<product, object>>[] includeProperties)
{
IQueryable<product> query = context.products;
foreach (var includeProperty in includeProperties) {
query = query.Include(includeProperty);
}
return query;
}
...
}
The Lazy Loading feature is actually the default behavior of
public interface IproductRepository : IDisposable
{
IEnumerable<product> All { get; }
IEnumerable<product> AllIncluding(params Expression<Func<product, object>>[] includeProperties);
product Find(string id);
void InsertOrUpdate(product product);
void Delete(string id);
void Save();
}
public class productRepository : IproductRepository
{
dbEntities context = new dbEntities();
public IEnumerable<product> All
{
get { return context.products.ToList(); }
}
public IEnumerable<product> AllIncluding(params Expression<Func<product, object>>[] includeProperties)
{
IQueryable<product> query = context.products;
foreach (var includeProperty in includeProperties) {
query = query.Include(includeProperty);
}
return query.ToList();
}
...
}
Hope this little trick saves you some headache and hair-pulling!
Cool, thanks for this trick.
ReplyDelete