【问题标题】:Custom Membership + Ninject + InRequestScope = ObjectContext instance has been disposedCustom Membership + Ninject + InRequestScope = ObjectContext 实例已被释放
【发布时间】:2023-12-19 23:53:01
【问题描述】:

ObjectContext 实例已在 InRequestScope 中释放!

我在网上试了几个小时试图解决一个问题。

ObjectContext 实例已被释放,不能再使用 用于需要连接的操作。

我发现了几篇具有相同问题的文章和帖子,例如thisthisthisthis

我尝试了所有方法,但总是出现错误。


代码

上下文

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>());
    }
}

忍者

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

存储库

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
}

对于ProjectImageRepositoryAddressRepositoryRoleRepositoryUserRepository 的实现遵循相同的模型!

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
}

由于范围是请求,Ninject 应该在请求结束时处理对象。但在某些情况下,dispose 会在完成请求之前发生。

尝试

我不确定问题是否与自定义成员资格有关,但我进行了一些测试。如下:

忍者

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

所以没有更多的错误!

但是出现了另一个问题!由于repositorycontext 是单例对象,因此不会更新。

比如我为项目注册了一个新地址,集合project.Addresses没有更新!

注意:地址在数据库中注册没有任何问题!

【问题讨论】:

    标签: asp.net-mvc-3 dependency-injection ninject dbcontext custom-membershipprovider


    【解决方案1】:

    Membership 和 RoleProviders 的生命周期比请求长。对象不应该依赖于生命周期较短的对象(除非在方法执行期间本地创建和销毁),因为它们最终会引用已释放的对象。

    由于您希望为每个请求创建一个新的上下文以避免缓存对象,因此您不能将上下文注入存储库,而是通过方法调用从外部传递它,并使用工厂在服务或提供程序中创建它。

    【讨论】:

      【解决方案2】:

      为避免此异常,请使用 DependencyResolver.Current.GetService() 而不是在具有长生命周期的类(操作过滤器、成员资格提供程序等)中注入属性。这种方法对测试不友好,但它允许您在使用 InRequestScope() 时访问当前 http-request 的数据上下文实例。

      【讨论】:

        【解决方案3】:

        我删除了依赖注入并这样做了......

            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));
        
                 }
        
            }
        

        【讨论】: