ASP.NET WebApi2 controller

public class BooksController : ApiController { public IRepository Repository { get; set; } public BooksController(IRepository r) { Repository = r; } ... } 

Repository:

 public class BookRepository : IRepository, IDisposable { public BookContext Context { get; set; } ... protected void Dispose(bool disposing) { if (disposing) { if (Context != null) { Context.Dispose(); Context = null; } } } public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } } 

Data context:

 public class BookContext : DbContext { public DbSet<Book> Books { get; set; } } 

Autofac is used as IoC, the container is configured in Global.asax:

 protected void Application_Start() { AutofacConfig.ConfigureContainer(); . . . } public class AutofacConfig { public static void ConfigureContainer() { var builder = new ContainerBuilder(); var config = GlobalConfiguration.Configuration; builder.RegisterType<BookRepository>().InstancePerRequest().As<IRepository>().WithProperty("Context", new BookContext()); builder.RegisterApiControllers(Assembly.GetExecutingAssembly()); var container = builder.Build(); config.DependencyResolver = new AutofacWebApiDependencyResolver(container); } } 

For some reason, with such a registration of the BookRepository type, a new instance of its Context property is not created with a new http request. That is, the first http-request to the API works, and the second one returns the following error: The operation cannot be completed because the DbContext has been disposed.

    1 answer 1

    For starters, I would advise you to rewrite your repository. I don't like 2 things in it:

    1. Injection into the property. In my opinion, if a class has mandatory dependencies, then they should be reflected in the constructor. Otherwise, it remains possible to create a class and not initialize the property, without which the class does not work.

    2. The second thing I don’t like is your implementation of IDisposable . Why do you need to divide it into 2 functions? Do you plan to add a finalizer to the heirs? I do not think so. I generally would not inherit from this class.

    In the end, after my edits, the repository will look something like this:

     public sealed class BookRepository : IRepository, IDisposable { public BookRepository(BookContext ctx) { _context = ctx; } private BookContext _context; public void Dispose() { _context?.Dispose(); _context = null; } } 

    Next, you register your repository and specify a specific value for the context that will be used for all repositories. Therefore, when you first request, the context is destroyed when the next request no longer works. I am not an expert on autofac, but I would register the context first in the container, and then the repository. Something like this:

     builder.RegisterType<BookContext>(); builder.RegisterType<BookRepository>().InstancePerRequest().As<IRepository>(); 

    No injections into the property are necessary, context dependency is declared in the constructor of the repository and must be picked up by the container automatically.

    • Thank you very much!!! So everything works: both Dispose, and the context is updated on subsequent requests - WabiSabi
    • @WabiSabi please - tym32167