Search code examples
asp.net-mvc-3entity-frameworkninject

DbContext Disposed after first request when using Ninject's InRequestScope()


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.


Solution

  • 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()