C# AspNet标识-自定义标识RoleClaim&;IdentityUserRole&;IdentityUser声明重复的外键
目前,我正在使用AspNetCore和配置dbcontext,如下所示:C# AspNet标识-自定义标识RoleClaim&;IdentityUserRole&;IdentityUser声明重复的外键,c#,asp.net-core,entity-framework-core,asp.net-identity,ef-fluent-api,C#,Asp.net Core,Entity Framework Core,Asp.net Identity,Ef Fluent Api,目前,我正在使用AspNetCore和配置dbcontext,如下所示: public class AppDbContext : IdentityDbContext<ApplicationUser, ApplicationRole, string, ApplicationUserClaim, ApplicationUserRole, IdentityUserLogin<string>, ApplicationRoleClaim, IdentityUserToken<str
public class AppDbContext : IdentityDbContext<ApplicationUser, ApplicationRole, string, ApplicationUserClaim, ApplicationUserRole, IdentityUserLogin<string>, ApplicationRoleClaim, IdentityUserToken<string>>
{
public AppDbContext(DbContextOptions<AppDbContext> options)
: base(options)
{ }
public class AppDbContext : IdentityDbContext<ApplicationUser, ApplicationRole, string, ApplicationUserClaim, ApplicationUserRole, IdentityUserLogin<string>, ApplicationRoleClaim, IdentityUserToken<string>>
{
public AppDbContext(DbContextOptions<AppDbContext> options)
: base(options)
{ }
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
var entitiesBuilder = Assembly.GetExecutingAssembly()
.GetTypes()
.Where(type => type.ContainsGenericParameters == false && type.GetInterface(nameof(IEntityBuilder)) != null)
.ToList();
foreach (var entityBuilder in entitiesBuilder)
{
var instance = Activator.CreateInstance(entityBuilder) as IEntityBuilder;
instance.RunConfiguration(builder);
}
// base.OnModelCreating(builder); move this line to the beginning of this method
}
}
这是因为当您从标识模型继承时,它已经指定了此关系和其他属性。您的代码刚刚添加了实体之间的其他关系。您可以在文档中阅读有关标识自定义的更多信息:表之间的关系已在identity的
IdentityDbContext
中设置。这意味着您不必显式地指定它们(使用导航道具/fluent api配置)
但是,看起来您希望将Guid/Uuid而不是字符串作为主键/外键的列类型。如果是这样的话,正确的方法是使用已经继承的类的泛型变体
例如,您可以只定义需要扩展的类并向其添加其他属性,这些属性将包含在DB迁移中:
public class ApplicationUser : IdentityUser<Guid>
{
}
public class ApplicationRole : IdentityRole<Guid>
{
}
之后,迁移将生成一个脚本,将PK/FKs更改为正确的列类型。如果需要从Identity扩展其他类型,可以使用最通用的
IdentityDbContext
变体,该变体需要大量的数据。请确保在AppDbContext
中配置ientitypeconfiguration
public class ApplicationDbContext : IdentityDbContext<ApplicationUser, ApplicationRole, string, ApplicationUserClaim, ApplicationUserRole, IdentityUserLogin<string>, ApplicationRoleClaim, IdentityUserToken<string>>
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{ }
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
builder.ApplyConfiguration(new ApplicationUserEntityBuilder());
builder.ApplyConfiguration(new ApplicationRoleEntityBuilder());
builder.ApplyConfiguration(new ApplicationUserClaimEntityBuilder());
builder.ApplyConfiguration(new ApplicationUserRoleEntityBuilder());
builder.ApplyConfiguration(new ApplicationRoleClaimEntityBuilder());
}
}
public类ApplicationDbContext:IdentityDbContext
{
公共应用程序DBContext(DbContextOptions选项)
:基本(选项)
{ }
模型创建时受保护的覆盖无效(ModelBuilder)
{
基于模型创建(生成器);
ApplyConfiguration(新的applicationSerentityBuilder());
ApplyConfiguration(新的ApplicationRoleEntityBuilder());
ApplyConfiguration(新的ApplicationUserClaimEntityBuilder());
ApplyConfiguration(新的ApplicationUserRoleEntityBuilder());
ApplyConfiguration(新的ApplicationRoleClaimEntityBuilder());
}
}
您使用的.net core和identity的哪个版本?我使用的是asp.net core 2.1.5和entityframework core 2.1.4是的,谢谢您的观点。我将行代码base.OnModelCreating(builder)放在方法末尾的原因。这样基类就覆盖了我配置的所有内容。详细信息见最终更新。再次感谢您。当然,我已经配置运行ApplyConfiguration,以便efcore生成脚本迁移。无论如何,谢谢:)谢谢你的观点,我刚刚更新了最后的更新。你可以看到我修复的细节
public class ApplicationUserClaimEntityBuilder : IEntityTypeConfiguration<ApplicationUserClaim>
{
public void Configure(EntityTypeBuilder<ApplicationUserClaim> builder)
{
builder.Property(p => p.UserId)
.HasColumnName(nameof(ApplicationUserClaim.UserId))
.HasColumnType("CHAR(36)");
builder.HasOne(p => p.User)
.WithMany(u => u.UserClaims)
.HasForeignKey(p => p.UserId)
.IsRequired();
}
}
public class ApplicationUserRoleEntityBuilder : IEntityTypeConfiguration<ApplicationUserRole>
{
public void Configure(EntityTypeBuilder<ApplicationUserRole> builder)
{
// still use default table name
builder.ToTable("AspNetUserRoles");
builder.HasKey(p => p.Id);
builder.Property(p => p.Id)
.ValueGeneratedOnAdd();
builder.HasOne(p => p.Role)
.WithMany(r => r.UserRoles)
.HasForeignKey(p => p.RoleId)
.IsRequired();
builder.HasOne(p => p.User)
.WithMany(r => r.UserRoles)
.HasForeignKey(p => p.UserId)
.IsRequired();
}
}
public class ApplicationRoleClaimEntityBuilder : IEntityTypeConfiguration<ApplicationRoleClaim>
{
public void Configure(EntityTypeBuilder<ApplicationRoleClaim> builder)
{
// still use default table name
builder.ToTable("AspNetRoleClaims");
builder.HasKey(p => p.Id);
builder.Property(p => p.Id)
.ValueGeneratedOnAdd();
builder.Property(p => p.RoleId)
.HasColumnName(nameof(ApplicationRoleClaim.RoleId))
.HasColumnType("CHAR(36)");
builder.HasOne(p => p.Role)
.WithMany(r => r.RoleClaims)
.HasForeignKey(p => p.RoleId)
.IsRequired();
}
}
migrationBuilder.CreateTable(
name: "AspNetRoleClaims",
columns: table => new
{
Id = table.Column<int>(nullable: false)
.Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
RoleId = table.Column<string>(type: "CHAR(36)", nullable: false),
ClaimType = table.Column<string>(nullable: true),
ClaimValue = table.Column<string>(nullable: true),
RoleId1 = table.Column<string>(nullable: true) // DUPLICATE
},
constraints: table =>
{
table.PrimaryKey("PK_AspNetRoleClaims", x => x.Id);
table.ForeignKey(
name: "FK_AspNetRoleClaims_AspNetRoles_RoleId",
column: x => x.RoleId,
principalTable: "AspNetRoles",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_AspNetRoleClaims_AspNetRoles_RoleId1",
column: x => x.RoleId1,
principalTable: "AspNetRoles",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
});
migrationBuilder.CreateTable(
name: "AspNetUserClaims",
columns: table => new
{
Id = table.Column<int>(nullable: false)
.Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
UserId = table.Column<string>(type: "CHAR(36)", nullable: false),
ClaimType = table.Column<string>(nullable: true),
ClaimValue = table.Column<string>(nullable: true),
UserId1 = table.Column<string>(nullable: true) //DUPLICATE
},
constraints: table =>
{
table.PrimaryKey("PK_AspNetUserClaims", x => x.Id);
table.ForeignKey(
name: "FK_AspNetUserClaims_AspNetUsers_UserId",
column: x => x.UserId,
principalTable: "AspNetUsers",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_AspNetUserClaims_AspNetUsers_UserId1",
column: x => x.UserId1,
principalTable: "AspNetUsers",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
});
migrationBuilder.CreateTable(
name: "AspNetUserRoles",
columns: table => new
{
UserId = table.Column<string>(nullable: false),
RoleId = table.Column<string>(nullable: false),
Id = table.Column<int>(nullable: false)
.Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
RoleId1 = table.Column<string>(nullable: true), //DUPLICATE
UserId1 = table.Column<string>(nullable: true) //DUPLICATE
},
constraints: table =>
{
table.PrimaryKey("PK_AspNetUserRoles", x => new { x.UserId, x.RoleId });
table.UniqueConstraint("AK_AspNetUserRoles_Id", x => x.Id);
table.ForeignKey(
name: "FK_AspNetUserRoles_AspNetRoles_RoleId",
column: x => x.RoleId,
principalTable: "AspNetRoles",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_AspNetUserRoles_AspNetRoles_RoleId1",
column: x => x.RoleId1,
principalTable: "AspNetRoles",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
table.ForeignKey(
name: "FK_AspNetUserRoles_AspNetUsers_UserId",
column: x => x.UserId,
principalTable: "AspNetUsers",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_AspNetUserRoles_AspNetUsers_UserId1",
column: x => x.UserId1,
principalTable: "AspNetUsers",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
});
public class AppDbContext : IdentityDbContext<ApplicationUser, ApplicationRole, string, ApplicationUserClaim, ApplicationUserRole, IdentityUserLogin<string>, ApplicationRoleClaim, IdentityUserToken<string>>
{
public AppDbContext(DbContextOptions<AppDbContext> options)
: base(options)
{ }
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
var entitiesBuilder = Assembly.GetExecutingAssembly()
.GetTypes()
.Where(type => type.ContainsGenericParameters == false && type.GetInterface(nameof(IEntityBuilder)) != null)
.ToList();
foreach (var entityBuilder in entitiesBuilder)
{
var instance = Activator.CreateInstance(entityBuilder) as IEntityBuilder;
instance.RunConfiguration(builder);
}
// base.OnModelCreating(builder); move this line to the beginning of this method
}
}
public class ApplicationUser : IdentityUser<Guid>
{
}
public class ApplicationRole : IdentityRole<Guid>
{
}
public class ApplicationUserDbContext : IdentityDbContext<ApplicationUser, ApplicationRole, Guid>
{
}
public class ApplicationDbContext : IdentityDbContext<ApplicationUser, ApplicationRole, string, ApplicationUserClaim, ApplicationUserRole, IdentityUserLogin<string>, ApplicationRoleClaim, IdentityUserToken<string>>
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{ }
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
builder.ApplyConfiguration(new ApplicationUserEntityBuilder());
builder.ApplyConfiguration(new ApplicationRoleEntityBuilder());
builder.ApplyConfiguration(new ApplicationUserClaimEntityBuilder());
builder.ApplyConfiguration(new ApplicationUserRoleEntityBuilder());
builder.ApplyConfiguration(new ApplicationRoleClaimEntityBuilder());
}
}