延长ASP。网络身份角色:身份角色不是当前上下文模型的一部分。

时间:2022-12-20 21:03:38

I'm trying to use the new ASP.NET Identity in my MVC5 application, specifically I'm trying to integrate ASP.NET Identity into an existing database. I've already read the questions/answers on SO pertaining to DB First and ASP.NET Identity, and having followed all the recommendations I still can't add roles to my database, although I have no problems adding users. Here's my code:

我正在尝试使用新的ASP。我的MVC5应用程序中的NET Identity,特别是我正在尝试集成ASP。将NET标识添加到现有数据库中。我已经读过关于DB和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

At the last line of code I get an exception of type 'System.InvalidOperationException': The entity type IdentityRole is not part of the model for the current context.

在最后一行代码中,我得到一个类型为'System '的异常。InvalidOperationException':实体类型IdentityRole不是当前上下文的模型的一部分。

Here is my 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; }
......
}

My AspNetUser and AspNetRole classes derive from IdentityUser and IdentityRole respectively, but I'm still getting that exception. Here is my database diagram:

我的AspNetUser和AspNetRole类分别来自身份用户和身份角色,但我仍然得到了这个异常。这是我的数据库图:

延长ASP。网络身份角色:身份角色不是当前上下文模型的一部分。

Any help would be greatly appreciated.

如有任何帮助,我们将不胜感激。

5 个解决方案

#1


9  

You have to specify during the creation of User Store that AspNetRole is used instead of IdentityRole. You can achieve this by using the UserStore class with 6 type parameters:

在创建用户存储时,必须指定使用AspNetRole而不是IdentityRole。您可以通过使用UserStore类并带有6个类型参数来实现这一点:

new UserStore<AspNetUser, AspNetRole, string, IdentityUserLogin, IdentityUserRole, IdentityUserClaim>(new PayrollDBEntities());

This indicates changes at User Manager creation as well. Here is a simplified example about the creation of needed instances:

这也表示在创建用户管理器时发生的更改。这里有一个关于创建所需实例的简化示例:

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);
        }
    }
}

#2


5  

After a few days of trying to get this to work in a clean manner, I've come to the conclusion that if you're using Database first and want to integrate ASP.NET Identity into your app, by far the easiest and cleanest solution is to create your own membership provider by overriding ASP.NET Identity. It's actually pretty easy, so far I've implemented UserStore and RoleStore to my liking. I've added columns/relations specific to my domain in my database, and whenever I create a user or a role, I take care of my database commits by adding the required relations. My UserStore implementation is quite similar to this. My RoleStore implementation is something like this:

在尝试以一种干净的方式工作几天之后,我得出这样的结论:如果您首先使用数据库,并希望集成ASP。NET Identity进入您的应用程序,到目前为止,最简单、最干净的解决方案是通过覆盖ASP创建您自己的成员资格提供者。净的身份。它实际上非常简单,到目前为止,我已经按照我的喜好实现了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,
        };
    }
}

And my ApplicationRoleDTO:

和我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; }
}

I also found these 2 articles pretty helpful:

我也发现这两篇文章很有帮助:

Overview of Custom Storage Providers for ASP.NET Identity

ASP的自定义存储提供程序概述。净的身份

Implementing a Custom MySQL ASP.NET Identity Storage Provider

实现自定义MySQL ASP。净身份存储提供商

#3


2  

I'll explain here with the code exampels :).

我将在这里用代码exampels:进行解释。

The trick is, they are already in the IdentityDbContext (AspNetRoles, AspNetUserClaims, AspNetUsers, ....)

关键是,他们已经在IdentityDbContext(AspNetRoles、AspNetUserClaims AspNetUsers,....)

In the IdentityModel you will see ApplicationUser is empty at the top. If you want to customize these users or roles, just add properties here and then update your database via the console

在标识模型中,您将看到ApplicationUser在顶部是空的。如果您想定制这些用户或角色,只需在这里添加属性,然后通过控制台更新数据库

Example of my context

的例子,我的背景

public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
    public ApplicationDbContext()
        : base("DefaultConnection")
    {
    }

    public DbSet<Request> Requests { get; set; }
    public DbSet<Reservation> Reservations { get; set; }
    public DbSet<PriceType> PriceTypes { get; set; }
    public DbSet<Product> Products { get; set; }
    public DbSet<Price> Prices { get; set; }
    public DbSet<GuestbookPost> Posts { get; set; }
    public DbSet<Count> Counts { get; set; }
    public DbSet<Invoice> Invoices { get; set; }
    public DbSet<InvoiceLine> InvoiceLines { get; set; }

    ...

}

So no application user is defined here, but I did add more properties to it, example:

这里没有定义应用程序用户,但是我添加了更多的属性,例如:

public class ApplicationUser : IdentityUser
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string GroupName { get; set; }
    public string Email { get; set; }
    [StringLength(15)]
    public string Phone { get; set; }
    public string Remark { get; set; }
    public DateTime? BirthDate { get; set; }
    public DateTime ValidFrom { get; set; }
    public DateTime ValidUntil { get; set; }

    public string Street { get; set; }
    public string ZipCode { get; set; }
    public string City { get; set; }

    public virtual ICollection<Request> Requests { get; set; } 
}

#4


1  

I know this is an old question, but just in case someone else is having a hard time adding roles/users when they modified asp identity to use numeric primary keys (int/long) instead of the default string for the Identity Roles, so if you have changed the IdentityUserRole in IdentityModels.cs to something like this:

我知道这是一个老问题,但如果其他人修改了asp标识以使用数字主键(int/long)而不是标识角色的默认字符串(因此,如果您更改了identitymodel中的IdentityUserRole),那么就很难添加角色/用户。像这样的cs:

public class Role : IdentityRole<long, UserRole>
{
    public Role() { }
    public Role(string name) { Name = name; }
}

You have to use the class Role instead of the default IdentityRole when constructing the RoleManager, so your code should be like this:

在构建RoleManager时,您必须使用类角色而不是默认的标识角色,因此您的代码应该如下所示:

public static void RegisterUserRoles()
{
     ApplicationDbContext context = new ApplicationDbContext();

     var RoleManager = new RoleManager<Role, long>(new RoleStore(context));

     if (!RoleManager.RoleExists("Administrador"))
     {
         var adminRole = new Role {
              Name = "Administrador",
         };
         RoleManager.Create(adminRole);
     }
}

So this should populate your database properly, I think all experienced ASP programmers already know this, but for others this could take some time to figure out.

所以这应该能很好地填充你的数据库,我认为所有有经验的ASP程序员都已经知道这个,但是对于其他人来说,这可能需要一些时间来弄清楚。

#5


-2  

I fixed this issue by changing the web.config DefaultConnection connectionString property so it points to the new SQLServer database

我通过改变网络解决了这个问题。配置DefaultConnection connectionString属性,因此它指向新的SQLServer数据库

#1


9  

You have to specify during the creation of User Store that AspNetRole is used instead of IdentityRole. You can achieve this by using the UserStore class with 6 type parameters:

在创建用户存储时,必须指定使用AspNetRole而不是IdentityRole。您可以通过使用UserStore类并带有6个类型参数来实现这一点:

new UserStore<AspNetUser, AspNetRole, string, IdentityUserLogin, IdentityUserRole, IdentityUserClaim>(new PayrollDBEntities());

This indicates changes at User Manager creation as well. Here is a simplified example about the creation of needed instances:

这也表示在创建用户管理器时发生的更改。这里有一个关于创建所需实例的简化示例:

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);
        }
    }
}

#2


5  

After a few days of trying to get this to work in a clean manner, I've come to the conclusion that if you're using Database first and want to integrate ASP.NET Identity into your app, by far the easiest and cleanest solution is to create your own membership provider by overriding ASP.NET Identity. It's actually pretty easy, so far I've implemented UserStore and RoleStore to my liking. I've added columns/relations specific to my domain in my database, and whenever I create a user or a role, I take care of my database commits by adding the required relations. My UserStore implementation is quite similar to this. My RoleStore implementation is something like this:

在尝试以一种干净的方式工作几天之后,我得出这样的结论:如果您首先使用数据库,并希望集成ASP。NET Identity进入您的应用程序,到目前为止,最简单、最干净的解决方案是通过覆盖ASP创建您自己的成员资格提供者。净的身份。它实际上非常简单,到目前为止,我已经按照我的喜好实现了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,
        };
    }
}

And my ApplicationRoleDTO:

和我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; }
}

I also found these 2 articles pretty helpful:

我也发现这两篇文章很有帮助:

Overview of Custom Storage Providers for ASP.NET Identity

ASP的自定义存储提供程序概述。净的身份

Implementing a Custom MySQL ASP.NET Identity Storage Provider

实现自定义MySQL ASP。净身份存储提供商

#3


2  

I'll explain here with the code exampels :).

我将在这里用代码exampels:进行解释。

The trick is, they are already in the IdentityDbContext (AspNetRoles, AspNetUserClaims, AspNetUsers, ....)

关键是,他们已经在IdentityDbContext(AspNetRoles、AspNetUserClaims AspNetUsers,....)

In the IdentityModel you will see ApplicationUser is empty at the top. If you want to customize these users or roles, just add properties here and then update your database via the console

在标识模型中,您将看到ApplicationUser在顶部是空的。如果您想定制这些用户或角色,只需在这里添加属性,然后通过控制台更新数据库

Example of my context

的例子,我的背景

public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
    public ApplicationDbContext()
        : base("DefaultConnection")
    {
    }

    public DbSet<Request> Requests { get; set; }
    public DbSet<Reservation> Reservations { get; set; }
    public DbSet<PriceType> PriceTypes { get; set; }
    public DbSet<Product> Products { get; set; }
    public DbSet<Price> Prices { get; set; }
    public DbSet<GuestbookPost> Posts { get; set; }
    public DbSet<Count> Counts { get; set; }
    public DbSet<Invoice> Invoices { get; set; }
    public DbSet<InvoiceLine> InvoiceLines { get; set; }

    ...

}

So no application user is defined here, but I did add more properties to it, example:

这里没有定义应用程序用户,但是我添加了更多的属性,例如:

public class ApplicationUser : IdentityUser
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string GroupName { get; set; }
    public string Email { get; set; }
    [StringLength(15)]
    public string Phone { get; set; }
    public string Remark { get; set; }
    public DateTime? BirthDate { get; set; }
    public DateTime ValidFrom { get; set; }
    public DateTime ValidUntil { get; set; }

    public string Street { get; set; }
    public string ZipCode { get; set; }
    public string City { get; set; }

    public virtual ICollection<Request> Requests { get; set; } 
}

#4


1  

I know this is an old question, but just in case someone else is having a hard time adding roles/users when they modified asp identity to use numeric primary keys (int/long) instead of the default string for the Identity Roles, so if you have changed the IdentityUserRole in IdentityModels.cs to something like this:

我知道这是一个老问题,但如果其他人修改了asp标识以使用数字主键(int/long)而不是标识角色的默认字符串(因此,如果您更改了identitymodel中的IdentityUserRole),那么就很难添加角色/用户。像这样的cs:

public class Role : IdentityRole<long, UserRole>
{
    public Role() { }
    public Role(string name) { Name = name; }
}

You have to use the class Role instead of the default IdentityRole when constructing the RoleManager, so your code should be like this:

在构建RoleManager时,您必须使用类角色而不是默认的标识角色,因此您的代码应该如下所示:

public static void RegisterUserRoles()
{
     ApplicationDbContext context = new ApplicationDbContext();

     var RoleManager = new RoleManager<Role, long>(new RoleStore(context));

     if (!RoleManager.RoleExists("Administrador"))
     {
         var adminRole = new Role {
              Name = "Administrador",
         };
         RoleManager.Create(adminRole);
     }
}

So this should populate your database properly, I think all experienced ASP programmers already know this, but for others this could take some time to figure out.

所以这应该能很好地填充你的数据库,我认为所有有经验的ASP程序员都已经知道这个,但是对于其他人来说,这可能需要一些时间来弄清楚。

#5


-2  

I fixed this issue by changing the web.config DefaultConnection connectionString property so it points to the new SQLServer database

我通过改变网络解决了这个问题。配置DefaultConnection connectionString属性,因此它指向新的SQLServer数据库