Назначение роли пользователю в расширенной ошибке Asp.Net Identity 2 Нарушение ограничения PRIMARY KEY «PK_dbo.AspNetUserRoles»

Я расширил AspNetUserRoles для своего приложения, добавив новый столбец FK ApplicationId в таблицу AspNetUserRoles. Идея заключается в том, чтобы позволить одному и тому же пользователю находиться в разных приложениях с одинаковыми или разными ролями. Кажется, все в порядке, пока я не попытался добавить ту же роль для того же пользователя, но для другого приложения, где я начал получать ошибку:

Нарушение ограничения PRIMARY KEY «PK_dbo.AspNetUserRoles». Не удается вставить повторяющийся ключ в объект «dbo.AspNetUserRoles».

Может ли кто-нибудь помочь мне выйти из этой проблемы.

мои IdenitityModels следующие

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

person Learning Curve    schedule 11.09.2015    source источник


Ответы (1)


IdentityUserRole реализует составной внешний ключ, совместимый с UserId и RoleId. В вашем подклассе есть только набор ключей для ApplicationId, поэтому происходит одно из двух:

  1. Ключ — ApplicationId, и в этом случае для любого данного приложения может быть добавлена ​​только одна роль пользователя.
  2. Ключ — UserId и RoleId, и поскольку это один и тот же пользователь и одна и та же роль, вы нарушаете ограничение.

По сути, вам необходимо убедиться, что составной ключ состоит из UserId, RoleId, и ApplicationId. Поскольку вы не можете контролировать базовую реализацию IdentityUserRole, лучший способ убедиться в этом — использовать плавную конфигурацию. Добавьте следующее в свой контекстный класс.

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<AspNetUserRoles>().HasKey(m => new { m.ApplicationId, m.UserId, m.RoleId });
}

Кроме того, FWIW, вам не нужно называть свои классы AspNet*. Если вам нужны одинаковые имена таблиц, просто украсьте класс [Table("AspNetUserRoles")].

person Chris Pratt    schedule 11.09.2015
comment
Ты прав Крис. Я намерен добавить ApplicationId в качестве составного ключа, и я попробовал ваш подход, при котором я вижу ApplicationId в качестве составного ключа в этой миграции, но он по-прежнему выдает ту же ошибку. сценарий вверх выглядит следующим образом: DropForeignKey(dbo.AspNetUserRoles, ApplicationId, dbo.AspNetApplications); AddForeignKey(dbo.AspNetUserRoles, ApplicationId, dbo.AspNetApplications, ApplicationId); - person Learning Curve; 11.09.2015
comment
Возможно, вам придется удалить базу данных и создать ее заново. Не похоже, что миграция подхватывает изменения с OnModelCreating. Вы добавили этот метод в свой подкласс DbContext, верно? - person Chris Pratt; 14.09.2015
comment
У меня все работает Спасибо, Крис. Аннотация данных внешнего ключа была проблемой. После удаления атрибута ForeignKey и переименования моего расширенного класса модели из AspNetUserRoles в ApplicationUserRoles он работает нормально. Тут у меня другой вопрос. Миграция создала новую таблицу «ApplicationUserRoles» с UserId, RoleId и ApplicationId в качестве составного первичного ключа. Не могли бы вы рассказать мне, как я могу использовать эту новую таблицу для аутентификации ролей, а не таблицу AspNetUserRoles? Мое удостоверение пользователя по-прежнему ссылается на AspNetUserRoles. Огромное спасибо - person Learning Curve; 14.09.2015