使用附加列 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:
中拥有 Id 和 identity: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 数据库更新
我有一个带有身份模型的 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:
中拥有 Id 和 identity:YesDbContext :
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 数据库更新