如何阻止自定义的基于ef的RoleProvider缓存结果?

本文关键字:缓存 RoleProvider 结果 ef 何阻止 自定义 | 更新日期: 2023-09-27 18:10:34

我有一个ASP。NET MVC 4应用程序,需要使用预先存在的用户/角色成员模型。我这样做的方法是实现一个自定义ASP。. NET RoleProvider来管理访问,它使用实体框架存储库从数据库读取用户数据。读取用户角色的方法如下所示,但是所有的方法实现都遵循这个模式:

public class OurRoleProvider : RoleProvider
{
    private IUserRepository _userRepository;
    public OurRoleProvider() : this(Container.Resolve<IUserRepository>())
    {
    }
    public OurRoleProvider(IUserRepository userRepository)
    {
        _userRepository = userRepository;
    }
    public override string[] GetRolesForUser(string username)
    {            
        var user = _userRepository.GetUserByUserName(username);            
        if (user.Roles.IsNullOrEmpty())
            return new string[0];
        return user.Roles.Select(r => r.RoleName).ToArray();
    }
}

我现在遇到了这篇文章中描述的问题。因为RoleProvider的单个实例在应用程序的生命周期内被重用,并且所有其他功能都会创建它自己的每个请求DbContext来持久化数据,所以对User配置文件所做的更改不会被RoleProvider反映,直到应用程序中重新启动,因为它的底层DbContext没有被刷新。这意味着你可以从一个角色中删除一个用户,并且他们仍然可以访问该角色的功能,直到应用程序重新启动。

我已经尝试在RoleProvider方法中创建一个新的存储库实例,即在GetRoleForUser():

var user = _userRepository.GetUserByUserName(username);

var userRepository = Container.Resolve<IUserRepository>();
var user = userRepository.GetUserByUserName(username);

这修复了这个问题,但破坏了不使用DI容器并通过构造函数注入模拟存储库的单元测试。会有很多单元测试需要重写。

如果可能的话,我想坚持使用自定义角色提供者,以利用诸如Authorize属性之类的功能。我真正需要做的是在每个请求的基础上重新实例化RoleProvider,或者强制EF存储库始终从数据库更新。到目前为止,我还没有找到这样做的方法。这可能吗?还是有更好的解决方案?

如何阻止自定义的基于ef的RoleProvider缓存结果?

你不应该将EF Services的生命周期定义为单例(它应该是per-request生命周期)。因为DbContext不是线程安全的,而且它的设计寿命很短。激活角色提供者的缓存是在其他地方完成的,在web中。配置文件:

<roleManager defaultProvider="CustomRoleProvider" cacheRolesInCookie="true" enabled="true">
  <providers>
    <clear />
    <add name="CustomRoleProvider" type="Security.CustomRoleProvider" />
  </providers>
</roleManager>

上面的自定义角色提供程序被缓存,因为它在这里使用了cacherolesinccookie ="true"