4
votes

I have an MVC4 web project and am using Castle Windsor as my DI container. Also, I am using Entity Framework to access a SQL database. I would like to set my Lifestyle to PerWebRequest, however, when I do so I get the following error: "The operation cannot be completed because the DbContext has been disposed".

If I use a Transient lifestyle, the error is bypassed, but it introduces a new set of problems with the Entity Framework. How can I keep the PerWebRequest lifestyle, but correct when the dispose method is called?

I am using constructor injection to pass my repository a connection string to build a new context. I also implement IDisposable. See below:

public class MySqlRepository : MyRepository, IDisposable
{
    private readonly DbContext _context;

    public MySqlRepository(string connectionString)
    {
        _context = new DbContext(connectionString);
    }

    protected virtual void Dispose(bool disposing)
    {
        if (disposing)
        {
            _context.Dispose();
        }
    }

    public void Dispose()
    {
        Dispose(true);
    }
}
2
The code seems to be correct. Are you sure that the components that are using the SqlRepository also have a PerWebReuquest or shorter lifestyle ?Marwijn

2 Answers

0
votes

This should not be a problem. I had this problem once and the reason was that my container was not right set up.

Here is a demo which works using castle windsor.

The container is set up like this:

container = new WindsorContainer();
container.Register(Classes.FromThisAssembly().BasedOn<Controller>().LifestylePerWebRequest());
container.Register(Classes.FromThisAssembly().InNamespace("MvcIoCDemo.Models").WithServiceDefaultInterfaces().LifestylePerWebRequest());

Controller:

public class ProductsController : Controller
{
    private readonly IProductRepository productRepository;

    public ProductsController(IProductRepository productRepository)
    {
        if (productRepository == null) throw new ArgumentNullException("productRepository");
        this.productRepository = productRepository;
    }

Repository:

public class ProductRepository : IDisposable, IProductRepository
{
    private readonly DemoDbContext context;

    public ProductRepository()
    {
        context = new DemoDbContext();
    }

See demo project here: https://github.com/kobbikobb/MvcIoCDemo

0
votes

After changing all of my registered components to use a lifestyle of PerWebRequest, I think my problem is stemming from the use of IEnumerable with the Entity Framework. Here is an issue very similar to mine. stackoverflow.com/questions/9691681/… I thought it was the lifestyle, but it may have to do with how I am interacting with EF.

I was able to retain use of the Lifestyle.PerWebRequest by calling .ToList() for any repository method with a return type if IEnumerable<>. This ensures that the data I need to access will be loaded into memory before the context is disposed of.