Question

ObjectContext instance has been disposed in InRequestScope!

I tried for several hours across the web to try to solve a problem.

The ObjectContext instance has been disposed and can no longer be used for operations that require a connection.

I found several articles and posts with the same problem like this, this, this and this

I tried all ways, but always an error occurs.


Code

Context

public class BindSolutionContext : DbContext
{
    public DbSet<Project> Projects { get; set; }
    public DbSet<User> Users { get; set; }
    public DbSet<Role> Roles { get; set; }
    public DbSet<Address> Addresses { get; set; }
    public DbSet<ProjectImage> ProjectImages { get; set; }

    public BindSolutionContext()
        : base("name=Data")
    {
        Database.SetInitializer(new DropCreateDatabaseIfModelChanges<BindSolutionContext>());
    }
}

Ninject

kernel.Bind<BindSolutionContext>().ToSelf().InRequestScope();

kernel.Bind<IProjectRepository>().To<ProjectRepository>().InRequestScope();
kernel.Bind<IUserRepository>().To<UserRepository>().InRequestScope();
kernel.Bind<IRoleRepository>().To<RoleRepository>().InRequestScope();
kernel.Bind<IAddressRepository>().To<AddressRepository>().InRequestScope();
kernel.Bind<IProjectImageRepository>().To<ProjectImageRepository>().InRequestScope();

Repository

public class ProjectRepository : IProjectRepository
{
    private readonly BindSolutionContext _context;

    public ProjectRepository(BindSolutionContext context)
    {
        _context = context;
    }

    public IQueryable<Project> Query(params Expression<Func<Project, object>>[] includeProperties)
    {
        return includeProperties.Aggregate<Expression<Func<Project, object>>,
            IQueryable<Project>>(_context.Projects, (current, includeProperty) => current.Include(includeProperty));
    }

    public IQueryable<Project> Query(int pageIndex, int pageSize, params Expression<Func<Project, object>>[] includeProperties)
    {
        return includeProperties.Aggregate<Expression<Func<Project, object>>,
            IQueryable<Project>>(_context.Projects, (current, includeProperty) => current.Include(includeProperty)).OrderBy(p => p.Name).Skip(pageIndex).Take(pageSize);
    }

    //Rest of Implementation
}

For ProjectImageRepository, AddressRepository, RoleRepository and UserRepository implementation follows the same model!

public class BindUserProvider : MembershipProvider
{
    [Inject]
    public IUserService UserService { get; set; }

    //Rest of implementation
}


public class BindRoleProvider : RoleProvider
{
    private IRoleService _roleServ;
    private IRoleService RoleServ { get { return _roleServ ?? (_roleServ = DependencyResolver.Current.GetService<IRoleService>()); } }

    private IUserService _userServ;
    private IUserService UserServ { get { return _userServ ?? (_userServ = DependencyResolver.Current.GetService<IUserService>()); } }

    //Rest of implementation
}

As the scope is request, the Ninject should dispose of object at then end of the request. But in some situations, dispose occurs before finalizing the request.

Attempts

I'm not sure if the problem is related to the Custom membership, but did some testing. follows:

Ninject

kernel.Bind<BindSolutionContext>().ToSelf().InTransientScope();

kernel.Bind<IProjectRepository>().To<ProjectRepository>().InSingletonScope();
kernel.Bind<IUserRepository>().To<UserRepository>().InSingletonScope();
kernel.Bind<IRoleRepository>().To<RoleRepository>().InSingletonScope();
kernel.Bind<IAddressRepository>().To<AddressRepository>().InSingletonScope();
kernel.Bind<IProjectImageRepository>().To<ProjectImageRepository>().InSingletonScope();

So there is no more error!

But another problem arises! As the repository and context are singleton objects are not updated.

For example, if I register a new address for the project, the collection project.Addresses is not updated !

Note: The address is registered in the database without any problems!

Was it helpful?

Solution

Membership and RoleProviders have a longer lifecycle than a request. Objects should never depend on shorter lived objects (unless locally created and destroyed during a method execution) because they would end up referencing disposed objects.

Since you want a new context foreach request to avoid having cached objects you must not inject the context into the repositories but pass it from outside with the method call and either create it in the services or the providers using a factory.

OTHER TIPS

To avoid this exception, use DependencyResolver.Current.GetService() instead of injected properties in classes that have long life cycle (action filters, membership providers etc.). This approach is not test friendly, but it lets you access a data context instance of the current http-request when you use InRequestScope().

I removed dependency injection and did it this way...

    public class CustomRoleProvider:RoleProvider
    {
        private IGroupService _groupService;
        private MyDbContext context;

         public CustomRoleProvider()
         {
              //  _groupService = DependencyResolver.Current.GetService<IGroupService>();
              context = new MyDbContext();
             _groupService = new GroupService(new GroupRepository(context), new AccountRepository(context));

         }

    }
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top