扩展ASP.NET标识角色:IdentityRole不是当前上下文模型的一部分

Moh*_*and 12 c# asp.net-mvc asp.net-mvc-5 asp.net-identity

我正在尝试在我的MVC5应用程序中使用新的ASP.NET标识,特别是我正在尝试将ASP.NET标识集成到现有数据库中.我已经阅读了有关DB First和ASP.NET Identity的问题/答案,并且已经遵循了所有建议,我仍然无法将角色添加到我的数据库中,尽管添加用户没有任何问题.这是我的代码:

var context = new PayrollDBEntities();
var roleManager = new RoleManager<AspNetRole>(new RoleStore<AspNetRole>(context));

bool roleExists = roleManager.RoleExists(roleDto.Name);
if (roleExists){
    return false;
}

var role = new AspNetRole(roleDto.Name){
    Name = roleDto.Name,
};

IdentityResult result = roleManager.Create(role);//Getting exception here
Run Code Online (Sandbox Code Playgroud)

在最后一行代码中,我得到了类型的异常 'System.InvalidOperationException': The entity type IdentityRole is not part of the model for the current context.

这是我的背景:

public partial class PayrollDBEntities : IdentityDbContext
{
        public PayrollDBEntities()
            : base("name=PayrollDBEntities")
        {
        }

        public virtual DbSet<AspNetRole> AspNetRoles { get; set; }
        public virtual DbSet<AspNetUserClaim> AspNetUserClaims { get; set; }
        public virtual DbSet<AspNetUserLogin> AspNetUserLogins { get; set; }
        public virtual DbSet<AspNetUser> AspNetUsers { get; set; }
......
}
Run Code Online (Sandbox Code Playgroud)

AspNetUserAspNetRole类分别来自IdentityUserIdentityRole,但我仍然得到那个例外.这是我的数据库图:

在此输入图像描述

任何帮助将不胜感激.

小智 8

您必须在创建用户存储期间指定使用AspNetRole而不是IdentityRole.您可以通过使用带有6个类型参数的UserStore类来实现此目的:

new UserStore<AspNetUser, AspNetRole, string, IdentityUserLogin, IdentityUserRole, IdentityUserClaim>(new PayrollDBEntities());
Run Code Online (Sandbox Code Playgroud)

这表示用户管理器创建时也会发生更改.以下是有关创建所需实例的简化示例:

public class AspNetUser : IdentityUser { /*customization*/ }

public class AspNetRole : IdentityRole { /*customization*/ }

public class PayrollDBEntities : IdentityDbContext //or : IdentityDbContext <AspNetUser, AspNetRole, string, IdentityUserLogin, IdentityUserRole, IdentityUserClaim> 
{
}

public class Factory 
{
    public IdentityDbContext DbContext 
    { 
        get 
        {
            return new PayrollDBEntities();
        } 
    }

    public UserStore<AspNetUser, AspNetRole, string, IdentityUserLogin, IdentityUserRole, IdentityUserClaim> UserStore
    {
        get 
        {                
            return new UserStore<AspNetUser, AspNetRole, string, IdentityUserLogin, IdentityUserRole, IdentityUserClaim>(DbContext);
        }
    }

    public UserManager<AspNetUser, string> UserManager
    { 
        get 
        {
            return new UserManager<AspNetUser, string>(UserStore);
        } 
    }

    public RoleStore<AspNetRole> RoleStore 
    {
        get 
        {
            return new RoleStore<AspNetRole>(DbContext);
        }
    }

    public RoleManager<AspNetRole> RoleManager 
    {
        get 
        {
            return new RoleManager<AspNetRole>(RoleStore);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


Moh*_*and 4

在尝试以干净的方式工作几天后,我得出的结论是,如果您首先使用数据库并希望将ASP.NET身份集成到您的应用程序中,那么这是迄今为止最简单,最干净的解决方案是通过重写ASP.NET标识来创建自己的成员资格提供程序.它实际上非常简单,到目前为止我已经实现UserStore并且RoleStore符合我的喜好.我在我的数据库中添加了特定于我的域的列/关系,每当我创建用户或角色时,我通过添加所需的关系来处理我的数据库提交.我的UserStore实现与非常相似.我的RoleStore实现是这样的:

public class ApplicationRoleStore : IRoleStore<ApplicationRoleDTO>
{
    private PayrollDBEntities _context;
    public ApplicationRoleStore() { }

    public ApplicationRoleStore(PayrollDBEntities database)
    {
        _context = database;
    }

    public Task CreateAsync(ApplicationRoleDTO role)
    {
        if (role == null)
        {
            throw new ArgumentNullException("RoleIsRequired");
        }
        var roleEntity = ConvertApplicationRoleDTOToAspNetRole(role);
        _context.AspNetRoles.Add(roleEntity);
        return _context.SaveChangesAsync();

    }

    public Task DeleteAsync(ApplicationRoleDTO role)
    {
        var roleEntity = _context.AspNetRoles.FirstOrDefault(x => x.Id == role.Id);
        if (roleEntity == null) throw new InvalidOperationException("No such role exists!");
        _context.AspNetRoles.Remove(roleEntity);
        return _context.SaveChangesAsync();
    }

    public Task<ApplicationRoleDTO> FindByIdAsync(string roleId)
    {
        var role = _context.AspNetRoles.FirstOrDefault(x => x.Id == roleId);

        var result = role == null
            ? null
            : ConvertAspNetRoleToApplicationRoleDTO(role);

        return Task.FromResult(result);
    }

    public Task<ApplicationRoleDTO> FindByNameAsync(string roleName)
    {

        var role = _context.AspNetRoles.FirstOrDefault(x => x.Name == roleName);

        var result = role == null
            ? null
            : ConvertAspNetRoleToApplicationRoleDTO(role);

        return Task.FromResult(result);
    }

    public Task UpdateAsync(ApplicationRoleDTO role)
    {

        return _context.SaveChangesAsync();
    }

    public void Dispose()
    {
        _context.Dispose();
    }
    private ApplicationRoleDTO ConvertAspNetRoleToApplicationRoleDTO(AspNetRole aspRole)
    {
        return new ApplicationRoleDTO{
            Id = aspRole.Id,
            EnterpriseId = aspRole.EnterpriseId,
            Name = aspRole.Name
        };
    }

    private AspNetRole ConvertApplicationRoleDTOToAspNetRole(ApplicationRoleDTO appRole)
    {
        return new AspNetRole{
            Id = appRole.Id,
            EnterpriseId = appRole.EnterpriseId,
            Name = appRole.Name,
        };
    }
}
Run Code Online (Sandbox Code Playgroud)

而我的ApplicationRoleDTO:

public class ApplicationRoleDTO : IRole
{
    public ApplicationRoleDTO()
    {
        Id = Guid.NewGuid().ToString();
    }

    public ApplicationRoleDTO(string roleName)
        : this()
    {
        Name = roleName;
    }
    public string Id { get; set; }
    public string Name { get; set; }
    public Guid EnterpriseId { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

我还发现这两篇文章非常有帮助:

ASP.NET身份的自定义存储提供程序概述

实现自定义MySQL ASP.NET身份存储提供程序