I am new to both EF and Ninject so forgive me if this does not make sense :)
I have an MVC3 application with the Ninject and Ninject.Web.Common references. I am trying to inject a DbContext into my repositories. What I am seeing is that on the first request, everything works wonderfully but the subsequent requests return:
System.InvalidOperationException: The operation cannot be completed because the DbContext has been disposed.
at System.Data.Entity.Internal.LazyInternalContext.InitializeContext()
at System.Data.Entity.Internal.Linq.DbQueryProvider.Execute[TResult](Expression expression)
at System.Linq.Queryable.SingleOrDefault[TSource](IQueryable`1 source, Expression`1 predicate)
My bindings:
kernel.Bind<ISiteDataContext>().To<SiteDataContext>().InRequestScope();
kernel.Bind<IProductRepository>().To<ProductRepository>();
kernel.Bind<IProductService>().To<ProductService>();
My Service class:
public class ProductService : IProductService {
[Inject]
public IProductRepository repository {get; set;}
...
}
My Repository class:
public class ProductRepository : IProductRepository {
[Inject]
public ISiteDataContext context {get; set;}
...
}
My SiteDataContext class:
public class SiteDataContext : DbContext, ISiteDataContext
{
static SiteDataContext()
{
Database.SetInitializer<SiteDataContext >(null);
}
public DbSet<Product> Products{ get; set; }
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
}
}
My controller:
public class ProductController {
[Inject]
public IProductService productService {get; set;}
...
}
If I remove .InRequestScope(), then it works fine - but then that causes problems with Entity Framework since objects are modified in multiple separate instances of the data context.
Set your repositories to be InRequestScope as well. They should dispose after each request.
Also with MVC you should be using constructor injection to inject your repository into your controller instance as well.
Naturally, soon after posting something clicked in my mind, and I was able to solve this.
The problem lies in the fact that the behavior of ActionFilters were changed in MVC3 and I had a filter that had my ProductService injected.
I suppose that the filter disposed of the service and that eventually disposed of the DbContext.
In my case, the solution was easy. I created a second DbContext that is used specifically for my filter. Since the filter does nothing more than query a select few tables to verify authorization to specific resources, I did not need the Unit of Work context that DbContext provides across a single request. I created a new service that uses the new DbContext. In this case, it is sufficient to be configured with InTransientScope()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With