在扩展的 Asp.Net Identity 2 错误中将角色分配给用户违反 PRIMARY KEY 约束“PK_dbo.AspNetUserRoles”

Posted

技术标签:

【中文标题】在扩展的 Asp.Net Identity 2 错误中将角色分配给用户违反 PRIMARY KEY 约束“PK_dbo.AspNetUserRoles”【英文标题】:Assigning a role to a user in extended Asp.Net Identity 2 error Violation of PRIMARY KEY constraint 'PK_dbo.AspNetUserRoles' 【发布时间】:2015-12-07 21:50:52 【问题描述】:

我为我的应用程序扩展了 AspNetUserRoles,我在 AspNetUserRoles 表中添加了一个新的 FK 列 ApplicationId。这背后的想法是允许同一用户在具有相同或不同角色的不同应用程序中。 一切似乎都很好,直到我尝试将相同的角色添加到同一个用户但对于我开始收到错误的不同应用程序:

违反主键约束“PK_dbo.AspNetUserRoles”。不能 在对象 'dbo.AspNetUserRoles' 中插入重复键。

请任何人帮助我摆脱这个问题。

我的身份模型如下

 public class ApplicationUser : IdentityUser

    public virtual AspNetApplications AspNetApplication  get; set; 
    public virtual AspNetUserRoles AspNetUserRoles  get; set; 

    public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
    
        var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
        return userIdentity;
    


public class ApplicationDbContext : IdentityDbContext<ApplicationUser>

    public ApplicationDbContext()
        : base("DefaultConnection", throwIfV1Schema: false)
    
    

    public static ApplicationDbContext Create()
    
        return new ApplicationDbContext();
    

    public DbSet<AspNetApplications> AspNetApplications  get; set; 
    public DbSet<AspNetUserRoles> AspNetUserRoles  get; set; 

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    
        base.OnModelCreating(modelBuilder);
    


我的 AspNetApplications 和 AspNetUserRoles 模型如下

public class AspNetApplications

    [Key]
    public string ApplicationId  get; set; 
    public string ApplicationName  get; set; 


public class AspNetUserRoles : IdentityUserRole

    [Key]
    public string ApplicationId  get; set; 

    [ForeignKey("ApplicationId")]
    public AspNetApplications AspNetApplications  get; set; 

以下是我添加 AspNetUserRoles 类型的新实体的代码,它在 dbContext.SaveChanges() 处引发错误

            var aspNetUserRole = new AspNetUserRoles
            
                UserId = userId,
                RoleId = roleId,
                ApplicationId = applicationId,
            ;

            dbContext.AspNetUserRoles.Add(aspNetUserRole);
            dbContext.SaveChanges();

【问题讨论】:

【参考方案1】:

IdentityUserRole 实现了一个与UserIdRoleId 一致的复合外键。您的子类只有 ApplicationId 的密钥集,因此发生了以下两种情况之一:

    密钥是ApplicationId,在这种情况下,任何给定的应用程序都只能添加一个用户角色。 关键是UserIdRoleId,因为它是同一个用户和同一个角色,所以你违反了约束。

本质上,您需要确保复合键由UserIdRoleIdApplicationId组成。由于您无法控制IdentityUserRole 的基本实现,因此确保这一点的最佳方法是使用流利的配置。将以下内容添加到您的上下文类中。

protected override void OnModelCreating(DbModelBuilder modelBuilder)

    modelBuilder.Entity<AspNetUserRoles>().HasKey(m => new  m.ApplicationId, m.UserId, m.RoleId );

另外,FWIW,你不需要将你的类命名为AspNet*。如果你想要相同的表名,只需用[Table("AspNetUserRoles")] 装饰类即可。

【讨论】:

你说得对,克里斯。我打算将 ApplicationId 添加为复合键,并且我尝试了您的方法,在该方法中我可以看到 ApplicationId 作为该迁移中的复合键,但它仍然抛出相同的错误。 up 脚本如下 DropForeignKey("dbo.AspNetUserRoles", "ApplicationId", "dbo.AspNetApplications"); AddForeignKey("dbo.AspNetUserRoles", "ApplicationId", "dbo.AspNetApplications", "ApplicationId"); 您可能需要炸毁您的数据库并重新创建它。迁移似乎没有从OnModelCreating 中获得变化。您确实将该方法添加到您的 DbContext 子类中,对吗? 我已经成功了,谢谢克里斯。外键数据注释是问题所在。删除 ForeignKey 属性并将我的扩展模型类从 AspNetUserRoles 重命名为 ApplicationUserRoles 后,它工作正常。这里我还有一个问题。迁移创建了一个新表“ApplicationUserRoles”,其中 UserId、RoleId 和 ApplicationId 作为复合主键。你能告诉我如何利用这个新表而不是 AspNetUserRoles 表进行角色身份验证吗?我的用户声明身份仍然引用 AspNetUserRoles。非常感谢

以上是关于在扩展的 Asp.Net Identity 2 错误中将角色分配给用户违反 PRIMARY KEY 约束“PK_dbo.AspNetUserRoles”的主要内容,如果未能解决你的问题,请参考以下文章

我们可以扩展 HttpContext.User.Identity 以在 asp.net 中存储更多数据吗?

ASP.NET Identity 使用TIP

如何更改 asp.net identity 3 (vnext) 使用的表名?

Asp.net Core 2.0 Identity.TwoFactorRememberMe 到期

在 ASP.NET 中使用 Identity 2.1 对用户进行身份验证和授权

Asp.Net Core 2.1 Identity - UserStore 依赖注入