You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

继承IdentityUser的ApplicationUser在EF更新数据库时的报错及低风险解决咨询

问题描述

尝试在继承IdentityUser的ApplicationUser与Transactions模型间建立一对多关系,相关模型代码如下:

ApplicationUser 代码

public class ApplicationUser : IdentityUser
{
    public ICollection<Transactions> Transactions { get; set; }
}

Transactions 代码

public class Transactions
{
    public int Id { get; set; }
    public int PhoneId { get; set; }
    public Phone Phone { get; set; }
    public int CustomerId { get; set; }
    public Customers Customer { get; set; }
    public string UserId { get; set; }
    public ApplicationUser User { get; set; }
    public TransactionType TransactionType { get; set; }
    public DateTime TransactionDate { get; set; }
    public decimal TransactionAmount { get; set; }
}

添加新迁移后,除创建Transactions表外,迁移文件还生成了修改AspNet系列系统表的操作:

migrationBuilder.AlterColumn<string>(
    name: "Name",
    table: "AspNetUserTokens",
    type: "nvarchar(128)",
    maxLength: 128,
    nullable: false,
    oldClrType: typeof(string),
    oldType: "nvarchar(450)");

migrationBuilder.AlterColumn<string>(
    name: "LoginProvider",
    table: "AspNetUserTokens",
    type: "nvarchar(128)",
    maxLength: 128,
    nullable: false,
    oldClrType: typeof(string),
    oldType: "nvarchar(450)");

migrationBuilder.AddColumn<string>(
    name: "Discriminator",
    table: "AspNetUsers",
    type: "nvarchar(max)",
    nullable: false,
    defaultValue: "");

migrationBuilder.AlterColumn<string>(
    name: "ProviderKey",
    table: "AspNetUserLogins",
    type: "nvarchar(128)",
    maxLength: 128,
    nullable: false,
    oldClrType: typeof(string),
    oldType: "nvarchar(450)");

migrationBuilder.AlterColumn<string>(
    name: "LoginProvider",
    table: "AspNetUserLogins",
    type: "nvarchar(128)",
    maxLength: 128,
    nullable: false,
    oldClrType: typeof(string),
    oldType: "nvarchar(450)");

执行Update-Database时出现错误:

Error Number:5074,State:1,Class:16
The object 'PK_AspNetUserTokens' is dependent on column 'Name'.
ALTER TABLE ALTER COLUMN Name failed because one or more objects access this column.

不想通过删除主键约束的方式解决,寻求低风险方案。

低风险解决方案

原因分析

报错是因为AspNetUserTokens表的主键由LoginProvider和Name列共同组成,EF Core生成的迁移尝试修改这两列的长度,但主键约束依赖这些列,直接修改会触发错误。这些修改操作并非建立ApplicationUser与Transactions关系所必需的,是EF Core对Identity默认配置的自动调整。


方案1:手动清理迁移文件(最直接)

打开生成的迁移文件,删除所有修改AspNetUserTokens和AspNetUserLogins列的代码块,只保留以下必要操作:

  • AspNetUsers表添加Discriminator列(继承IdentityUser必须)
  • 创建Transactions表及关联外键的代码

修改后的迁移文件仅保留核心逻辑,示例如下:

public partial class AddTransactionsAndUserRelationship : Migration
{
    protected override void Up(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.AddColumn<string>(
            name: "Discriminator",
            table: "AspNetUsers",
            type: "nvarchar(max)",
            nullable: false,
            defaultValue: "");

        migrationBuilder.CreateTable(
            name: "Transactions",
            columns: table => new
            {
                Id = table.Column<int>(type: "int", nullable: false)
                    .Annotation("SqlServer:Identity", "1, 1"),
                PhoneId = table.Column<int>(type: "int", nullable: false),
                CustomerId = table.Column<int>(type: "int", nullable: false),
                UserId = table.Column<string>(type: "nvarchar(450)", nullable: true),
                TransactionType = table.Column<int>(type: "int", nullable: false),
                TransactionDate = table.Column<DateTime>(type: "datetime2", nullable: false),
                TransactionAmount = table.Column<decimal>(type: "decimal(18,2)", nullable: false)
            },
            constraints: table =>
            {
                table.PrimaryKey("PK_Transactions", x => x.Id);
                table.ForeignKey(
                    name: "FK_Transactions_AspNetUsers_UserId",
                    column: x => x.UserId,
                    principalTable: "AspNetUsers",
                    principalColumn: "Id",
                    onDelete: ReferentialAction.Restrict);
                // 其他外键约束(Phone、Customer)
            });

        migrationBuilder.CreateIndex(
            name: "IX_Transactions_UserId",
            table: "Transactions",
            column: "UserId");
    }

    protected override void Down(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.DropTable(
            name: "Transactions");

        migrationBuilder.DropColumn(
            name: "Discriminator",
            table: "AspNetUsers");
    }
}

清理完成后,重新执行Update-Database即可。


方案2:配置Identity列长度与数据库现有值匹配

在DbContext的OnModelCreating方法中,显式配置Identity系统表的列长度,与数据库中现有长度一致(即nvarchar(450)),这样EF Core就不会生成修改列的迁移操作。

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    base.OnModelCreating(modelBuilder);

    // 配置AspNetUserTokens列长度,匹配现有数据库
    modelBuilder.Entity<IdentityUserToken<string>>()
        .Property(t => t.LoginProvider)
        .HasMaxLength(450);
    modelBuilder.Entity<IdentityUserToken<string>>()
        .Property(t => t.Name)
        .HasMaxLength(450);

    // 配置AspNetUserLogins列长度
    modelBuilder.Entity<IdentityUserLogin<string>>()
        .Property(l => l.LoginProvider)
        .HasMaxLength(450);
    modelBuilder.Entity<IdentityUserLogin<string>>()
        .Property(l => l.ProviderKey)
        .HasMaxLength(450);

    // 显式配置ApplicationUser与Transactions的一对多关系
    modelBuilder.Entity<ApplicationUser>()
        .HasMany(u => u.Transactions)
        .WithOne(t => t.User)
        .HasForeignKey(t => t.UserId)
        .OnDelete(DeleteBehavior.Cascade);
}

配置完成后,删除之前生成的迁移文件,重新执行Add-Migration生成新的迁移,再执行Update-Database。


方案3:生成SQL脚本并手动编辑

如果不想修改迁移文件,可先生成SQL迁移脚本,手动移除修改AspNetUserTokens和AspNetUserLogins列的语句,再执行脚本:

  1. 执行命令生成脚本:
    • Package Manager Console:Script-Migration
    • CLI:dotnet ef migrations script
  2. 在生成的SQL脚本中,删除所有修改AspNetUserTokens和AspNetUserLogins列的ALTER TABLE语句
  3. 在数据库管理工具(如SSMS)中执行修改后的脚本

内容的提问来源于stack exchange,提问作者Marko Mrđa

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 11:57:58