使用附加列 ASP.NET Core EF 扩展 UserRole 主键

Extending UserRole primary key with additional columns ASP.NET Core EF

我有一个带有身份模型的 ASP.Net 核心项目。它使用带有 Pomelo MySQL 提供程序的 10.4.17-MariaDB 数据库。该项目已在生产中使用,但我想在最新版本中使用新密钥扩展 UserRole。我已经定义了我自己的 UserRole class,它像这样扩展了 IdentityUserRole:

public class UserRole : IdentityUserRole<String>
{
    [Key]
    public Guid OrganizationId { get; set; }
    [Key]
    public DateTime Join { get; set; }
    ...
}

所以我希望我的用户在具有多个 'join' 日期的多个组织中担任多个角色。我手动将 HasKey 行添加到数据库上下文中的实体:

modelBuilder.Entity<UserRole>(entity =>
{
    entity.HasKey(m => new { m.UserId, m.RoleId, m.Join, m.OrganizationId });
    entity.Property(m => m.UserId).HasMaxLength(127);
    entity.Property(m => m.RoleId).HasMaxLength(127);
    entity.Property(m => m.OrganizationId).HasMaxLength(127);
    entity.Property(m => m.Join);
    ...
});

当我添加具有这些更改的迁移并尝试执行它时,出现以下错误:

Failed executing DbCommand (31ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
ALTER TABLE `AspNetUserRoles` ADD CONSTRAINT `FK_AspNetUserRoles_AspNetRoles_RoleId` FOREIGN KEY (`RoleId`) REFERENCES `AspNetRoles` (`RoleId`) ON DELETE CASCADE;

如果 AspNetRoles table 的主键称为 Id,为什么迁移会尝试引用 RoleId

我使用 Script-Migration 命令检查了第一次迁移,并且在 table 创建期间外键正确引用到 Id

原来这是我使用的 Pomelo 库的 alpha 版本中的一个错误。到那时,该错误已经在夜间构建中得到修复。请参阅 Github 上的问题 #1371

我们必须为 asp.net 核心身份管理器功能保留这些 两列 PK { u.UserId, u.RoleId } 例如:userManager.AddToRoleAsync()

如果你想在 UserRole table:

中拥有 Ididentity:Yes

DbContext :

namespace Attendance.Server.Data;

public class AppDbContext : IdentityDbContext<User, Role, int, UserClaim, UserRole, UserLogin, RoleClaim, UserToken>, IUnitOfWork
{
    public AppDbContext(DbContextOptions<AppDbContext> options) : base(options) { }

    public Task<int> SaveChangesAsync()
    {
        return base.SaveChangesAsync();
    }

    public void MarkAsDeleted<TEntity>(TEntity entity) => base.Entry(entity).State = EntityState.Deleted;

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);
 modelBuilder.ApplyConfigurationsFromAssembly(typeof(UserConfig).Assembly);
        
    }
}

用户角色:

namespace Attendance.Server.Data.Entities;

public partial class UserRole : IdentityUserRole<int>
{
    public int Id { get; set; }
}

用户角色配置 :

namespace Attendance.Server.Data.Configs;

public class UserRoleConfig : IEntityTypeConfiguration<UserRole>
{
    public void Configure(EntityTypeBuilder<UserRole> builder)
    {
        builder.ToTable("UserRole").HasKey(ur => new { ur.Id });
        builder.Property(p => p.Id).ValueGeneratedOnAdd();
        // we have to keep these two column PK for asp.net core identity managers functionality for example : userManager.AddToRoleAsync()
        builder.HasKey(u => new { u.UserId, u.RoleId }); 
        builder.Property(p => p.Id).HasColumnOrder(1);

        // seed
        builder.HasData(
            new UserRole { Id = 1, UserId = 1, RoleId = 1 }
        );
    }
}

然后迁移到数据库:

dotnet ef 迁移添加 createDb -o data/migrations

dotnet ef 数据库更新

如果迁移时出错,请通过 ssms 删除数据库并再次执行此命令:dotnet ef 数据库更新