自定义 RoleProvider 一直缓存我的存储库对象

3

我为一个项目实现了一个自定义的RoleProvider。RoleProvider可以使用,但是我用来获取用户角色的存储库仅在构建后填充。当我注销、更改用户角色、重新登录时,用户仍然保持旧角色。

public class CmsRoleProvider : RoleProvider
{
    private EntityDB _db { get; set; }

    public CmsRoleProvider()
    {
        _db = new EntityDB();
    }

    public override string[] GetRolesForUser(string username)
    {
        var user = _db.Users.Where(u => u.EmailAddress == username).SingleOrDefault();
        var roles = user.UserRoles.Select(u => u.Role.Name).ToList<string>();

        return roles.ToArray();
    }
}

在上面的示例中,用户只有在构建项目后才能获得正确的角色。当我在GetRolesForUser函数内创建存储库时,它可以正常工作。
是否存在缓存问题?谁能帮助我解决这个问题。

你是如何在哪里更改用户角色的? - Vinicius Ottoni
我直接在数据库中添加或删除角色。 - jpderooy
1
所以,请看我的答案,你就会明白了。如果还有不懂的地方,请告诉我。 =) - Vinicius Ottoni
2个回答

7

ASP.NET只创建RoleProvider的单个实例。因此,您的上下文也具有长寿命。最好使用短寿命上下文。

public class CmsRoleProvider : RoleProvider
{        
    private EntityDB GetContext()
    {
       return new EntityDB();
    }

    public override string[] GetRolesForUser(string username)
    {
        using(var db = GetContext())
        {
            var user = db.Users.Where(u => u.EmailAddress == username)
                          .SingleOrDefault();
            var roles = user.UserRoles.Select(u => u.Role.Name).ToList<string>();

            return roles.ToArray();
        }
    }
}

您的方法存在问题,因为上下文会跟踪已加载的用户。当您请求一个已由上下文跟踪的用户时,将返回现有实例。因此,与该用户相关联的UserRoles也将被返回。

谢谢!我通过将EntityDB _db = new EntityDB();放在GetRolesForUser方法内部来解决了它。您的建议更加优雅 :) - jpderooy
1
@jpderooy 别忘了将 EntityDB _db = new EntityDB(); 放在 using 块中。你可以将这个标记为被接受的答案。 - Eranga

2
问题在于上下文引用。当您在获取角色的方法之外创建上下文(EntityDB)的引用时,该引用仍然相同,换句话说,您选择的每个数据都将是相同的,因为选择将在上下文而不是数据库中进行(这是EF不一直到数据库的一种方式)。您所做的更改(在角色中)是在另一个上下文中进行的,因此要获得正确的上下文,您必须创建上下文的新实例。在方法内使用关键字using执行此操作:
using (var database = new EntityDB())
{
    // Get your roles and return them
}

如果这对你有帮助,你可以投票支持一下,帮助其他遇到同样问题的人。不管怎样,随时欢迎再来!=) - Vinicius Ottoni
我是一个新手,所以我需要赚取更多的声望才能投票支持 ;) - jpderooy
谢谢!那么,让我们在这里学到更多知识并传递它!=) - Vinicius Ottoni

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接