2015-11-06 79 views
0

我的DbContext在我的CustomRoleProvider中被使用時處理出現問題。DbContext已部署在自定義RoleProvider中

我設置我的綁定喜歡:

kernel.Bind<IUnitOfWork>().To<UnitOfWork>().InRequestScope(); 
kernel.Bind(typeof(IGenericRepository<>)).To(typeof(GenericRepository<>)).InRequestScope(); 
kernel.Bind<MyContext>().ToSelf().InRequestScope(); 

我使用這個NuGet包Ninject.MVC5 v3.2.1.0因此Ninject設置爲MVC中的主要DependencyResolver。因此,爲什麼我能夠做到這一點DependencyResolver.Current.GetService<IGenericRepository<User>>()

但由於某種原因上下文處置。

我嘗試添加該綁定到我的設置:

kernel.Bind<MyContext>().ToSelf().WhenInjectedInto<RoleProvider>(); 

但是,這並不工作。我也嘗試通過物業注入進行注射

[Inject] 
public IGenericRepository<User> UserRepository { get; set; }; 

但是,這隻會導致很多其他問題,我無法解決(但)。

據我可以告訴從錯誤消息它是在這裏觸發的問題。

public abstract class BaseController : Controller 
{ 
    protected override void OnActionExecuting(ActionExecutingContext filterContext) 
    { 
     User.IsInRole("Admin"); // calls my CustomRoleProvider 
     base.OnActionExecuting(filterContext); 
    } 
} 

CustomRoleProvider實施

public class CustomRoleProvider : RoleProvider 
{ 
    private readonly IGenericRepository<User> _userRepository; 

    public CustomRoleProvider() 
    { 
     // using Service Locator (anti pattern) 
     // cause MVC do not support DI in role providers (yet) 
     _userRepository = DependencyResolver.Current.GetService<IGenericRepository<User>>(); 
    } 

    public override bool IsUserInRole(string username, string roleName) 
    { 
     var user = _userRepository.AsQueryable().Where(x => x.Username == username && x.Role.Name == roleName); // dbcontext is here disposed... 
     return user.Any(); 
    } 

    public override string[] GetRolesForUser(string username) 
    { 
     var user = _userRepository.AsQueryable().Where(x => x.Username == username).Select(x => x.Role.Name); // dbcontext is here disposed... 
     return user.ToArray(); 
    } 

    // omitted... 
} 

IGenericRepository<T>實施

public class GenericRepository<T> : IGenericRepository<T> 
    where T : class 
{ 
    private readonly MyContext _context; 
    private readonly DbSet<T> _dbSet; 

    public GenericRepository(MyContext context) 
    { 
     _context = context; 
     _dbSet = context.Set<T>(); 
    } 

    public IQueryable<T> AsQueryable() 
    { 
     return _dbSet.AsQueryable(); 
    } 
} 

錯誤消息

[InvalidOperationException: The operation cannot be completed because the DbContext has been disposed.] 
    System.Data.Entity.Internal.InternalContext.CheckContextNotDisposed() +34 
    System.Data.Entity.Internal.LazyInternalContext.InitializeContext() +30 
    System.Data.Entity.Internal.InternalContext.Initialize() +21 
    System.Data.Entity.Internal.InternalContext.GetEntitySetAndBaseTypeForType(Type entityType) +20 
    System.Data.Entity.Internal.Linq.InternalSet`1.Initialize() +79 
    System.Data.Entity.Internal.Linq.InternalSet`1.get_InternalContext() +21 
    System.Data.Entity.Infrastructure.DbQuery`1.System.Linq.IQueryable.get_Provider() +64 
    System.Linq.Queryable.Where(IQueryable`1 source, Expression`1 predicate) +81 
    Presentation.Web.Providers.CustomRoleProvider.GetRolesForUser(String username) in ~\Application\Presentation.Web\Providers\CustomRoleProvider.cs:38 
    System.Web.Security.RolePrincipal.IsInRole(String role) +183 
    Presentation.Web.Controllers.BaseController.OnActionExecuting(ActionExecutingContext filterContext) in ~\Application\Presentation.Web\Controllers\BaseController.cs:27 
    ... 
+0

你似乎已經修剪了任何代碼,這些代碼實際上可以幫助我們確定上下文被處置的位置!你可以在? – DavidG

+0

中添加?你在想什麼?對我來說,這就是運行的所有代碼:) –

+0

那麼開始的'IsUserInRole'方法的內容。 – DavidG

回答

2

因此很明顯,壽命RoleProvider我的週期是MVC應用程序的整個生命週期。 (不記得我讀它)

所以必須解決每個方法:(依賴

public class CustomRoleProvider : RoleProvider 
{ 
    public override bool IsUserInRole(string username, string roleName) 
    { 
     var userRepository = DependencyResolver.Current.GetService<IGenericRepository<User>>(); 
     var user = userRepository .AsQueryable().Where(x => x.Username == username && x.Role.Name == roleName); // dbcontext is here disposed... 
     return user.Any(); 
    } 

    public override string[] GetRolesForUser(string username) 
    { 
     var userRepository = DependencyResolver.Current.GetService<IGenericRepository<User>>(); 
     var user = userRepository .AsQueryable().Where(x => x.Username == username).Select(x => x.Role.Name); // dbcontext is here disposed... 
     return user.ToArray(); 
    } 

    // omitted... 
} 

不明白爲什麼這不工作,那麼

kernel.Bind<MyContext>().ToSelf().WhenInjectedInto<RoleProvider>(); 

我甚至嘗試過添加InSingletonScope

+0

啊,是的,是有道理的。 – DavidG

+0

至於爲什麼最後一行代碼沒有幫助,你的角色提供者只能創建一次,所以它沒有區別。 – DavidG

+0

但是,如果將DbContext注入RoleProvider時是單例,那麼它不應該被處置 –