【问题标题】:MVC Custom Membership and Role Provider context lifetime issueMVC 自定义成员资格和角色提供者上下文生命周期问题
【发布时间】:2014-02-18 11:41:03
【问题描述】:

我在 MVC 4 中遇到自定义成员资格问题 当我执行 ajax 调用以从服务器(控制器)获取部分结果时,我不断收到与上下文生命周期相关的错误,错误始终是 {"The provider has been关闭”} 或 {“已经有一个打开的 DataReader 与此命令关联,必须先关闭。”} 错误总是出现在自定义 RoleProvider 中。 我将尝试解释我正在使用的当前设置。

我继承了 Membership 和 RoleProvier 并重写了所有类似的方法

public class CustomRoleProvider : RoleProvider
{
        private IAccountService _accountService;

        public CustomRoleProvider()
        {
            _accountService = new AccountService();
        }
        public override string[] GetRolesForUser(string username)
        {
             return _accountService.GetRolesForUser(username);
        }
}

Membership 提供者的实现方式与上面的 IAccountService 相同,它是处理所有用户帐户和角色的服务层所有服务层类都实现了一个名为 ServiceBase 的基础服务类,它创建了 DB 上下文

public class ServiceBase
{
    protected Context Context;

    protected ServiceBase() : this("Context") {}

    protected ServiceBase(string dbName)
    {
        IDatabaseInitializer<Context> initializer = new DbInitialiser();
        Database.SetInitializer(initializer);
        Context = new Context(dbName);
    }
}

拥有 ajax 的控制器

[Authorize(Roles = "Administrator,Supplier")]
public class AuctionController : Controller
{
    private IAuctionService _service;

    public AuctionController()
    {
        _service = new AuctionService();
    }
    public AuctionController(IAuctionService service)
    {
        _service = service;
    }
    [CacheControl(HttpCacheability.NoCache), HttpGet]
    public ActionResult RefreshAuctionTimes(int auctionId)
    {
        return PartialView("_AuctionTimer", BusinessLogic.Map.ConvertAuction(_service.GetAuction  (auctionId)));
     }

}

当我将[Authorize(Roles = "Administrator,Supplier")] 属性添加到处理 ajax 调用的控制器时,问题才开始出现,我知道这是 DbContext 的生命周期,用于应用程序的生命周期,并且控制器服务层被销毁并重新创建每个帖子,但我不确定处理这个问题的最佳方法,我以前使用过这个设置,但使用 DI 和 Windsor,并且从未遇到过这个问题,因为 IOC 正在控制上下文。

最好为提供者创建自己的数据库上下文,还是两个提供者之间存在冲突,他们真的需要共享相同的数据库上下文?

任何帮助都会非常感谢

【问题讨论】:

    标签: asp.net asp.net-mvc custom-membershipprovider


    【解决方案1】:

    问题正是您所怀疑的。是由于您正在创建 DbContext 的单个实例,因此您遇到了连接问题。如果您将它与 IOC/DI 模式一起使用,您将修复它。另一种选择是手动处理连接。

    here 是一个使用 Ninject 作为 IOC 容器的示例 他们需要共享相同的上下文才能停止问题。

    【讨论】:

    • 干杯,正如我预期的那样,我实际上可能会使用下面的 Joe 方法作为解决方法,因为没有时间在应用程序 atm 中实现 IOC,但这是迄今为止更清洁的选择。
    【解决方案2】:

    我建议您在每次调用 GetRolesForUser 时创建您的服务层类:

    public override string[] GetRolesForUser(string username)
    {
         return new AccountService().GetRolesForUser(username);
    }
    

    【讨论】:

    • 谢谢乔,简单但没想到:) 应该只是花时间在项目的早期实施 IOC... 我已将上述答案标记为最佳解决方案,因为我感觉是这样,但我可能会使用您的想法进行快速修复。谢谢!
    • @Troublesum,我不确定使用 IOC 注入您的服务是否足以解决您的问题。您的提供者的 GetRolesForUser 方法可以从多个线程调用,因此需要是线程安全的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-24
    • 1970-01-01
    • 2011-09-29
    • 1970-01-01
    • 2013-01-30
    相关资源
    最近更新 更多