Entity Framework - Объект PK_AspNetUserTokens зависит от столбца UserId

Я создал новый проект ASP.NET Core 2 MVC в VS 2017 (версия 15.5), изменил тип идентификатора пользователя со строки на Guid (также изменил имя класса ApplicationUser на User), добавил свои модели, а затем

Add-Migration Init
Update-Database

но он генерирует ошибку и база данных не будет создана.

The object 'PK_AspNetUserTokens' is dependent on column 'UserId'.
ALTER TABLE ALTER COLUMN UserId failed because one or more objects access this column.

Вот мой контекст:

public class ApplicationDbContext : IdentityDbContext<User, IdentityRole<Guid>, Guid>
{
    public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
        : base(options)
    {
    }

    public DbSet<TvShow> TvShows { get; set; }
    public DbSet<Episode> Episodes { get; set; }
    public DbSet<Subscription> Subscriptions { get; set; }
    public DbSet<Notification> Notifications { get; set; }
    public DbSet<Genre> Genres { get; set; }
    public DbSet<TvShowGenre> TvShowGenre { get; set; }

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

        builder.Entity<Subscription>()
            .HasKey(c => new { c.TvShowId, c.UserId });

        builder.Entity<TvShowGenre>()
            .HasKey(c => new { c.TvShowId, c.GenreId });
    }
}

Вот мой класс миграции (только метод up):

public partial class Init : Migration
{
    protected override void Up(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.DropIndex(
            name: "UserNameIndex",
            table: "AspNetUsers");

        migrationBuilder.DropIndex(
            name: "IX_AspNetUserRoles_UserId",
            table: "AspNetUserRoles");

        migrationBuilder.DropIndex(
            name: "RoleNameIndex",
            table: "AspNetRoles");

        migrationBuilder.AlterColumn<Guid>(
            name: "UserId",
            table: "AspNetUserTokens",
            nullable: false,
            oldClrType: typeof(string));

        migrationBuilder.AlterColumn<Guid>(
            name: "Id",
            table: "AspNetUsers",
            nullable: false,
            oldClrType: typeof(string));

        migrationBuilder.AlterColumn<Guid>(
            name: "RoleId",
            table: "AspNetUserRoles",
            nullable: false,
            oldClrType: typeof(string));

        migrationBuilder.AlterColumn<Guid>(
            name: "UserId",
            table: "AspNetUserRoles",
            nullable: false,
            oldClrType: typeof(string));

        migrationBuilder.AlterColumn<Guid>(
            name: "UserId",
            table: "AspNetUserLogins",
            nullable: false,
            oldClrType: typeof(string));

        migrationBuilder.AlterColumn<Guid>(
            name: "UserId",
            table: "AspNetUserClaims",
            nullable: false,
            oldClrType: typeof(string));

        migrationBuilder.AlterColumn<Guid>(
            name: "Id",
            table: "AspNetRoles",
            nullable: false,
            oldClrType: typeof(string));

        migrationBuilder.AlterColumn<Guid>(
            name: "RoleId",
            table: "AspNetRoleClaims",
            nullable: false,
            oldClrType: typeof(string));

        migrationBuilder.CreateTable(
            name: "Genres",
            columns: table => new
            {
                Id = table.Column<long>(nullable: false)
                    .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
                Genres = table.Column<int>(nullable: false),
                IsFirst = table.Column<bool>(nullable: false)
            },
            constraints: table =>
            {
                table.PrimaryKey("PK_Genres", x => x.Id);
            });

        migrationBuilder.CreateTable(
            name: "Notifications",
            columns: table => new
            {
                Id = table.Column<long>(nullable: false)
                    .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
                CreateDate = table.Column<DateTime>(nullable: false),
                Message = table.Column<string>(nullable: true),
                Seen = table.Column<bool>(nullable: false),
                UserId = table.Column<Guid>(nullable: false)
            },
            constraints: table =>
            {
                table.PrimaryKey("PK_Notifications", x => x.Id);
                table.ForeignKey(
                    name: "FK_Notifications_AspNetUsers_UserId",
                    column: x => x.UserId,
                    principalTable: "AspNetUsers",
                    principalColumn: "Id",
                    onDelete: ReferentialAction.Cascade);
            });

        migrationBuilder.CreateTable(
            name: "TvShows",
            columns: table => new
            {
                Id = table.Column<long>(nullable: false)
                    .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
                ProductionYear = table.Column<string>(nullable: true),
                Status = table.Column<int>(nullable: false),
                Title = table.Column<string>(nullable: true)
            },
            constraints: table =>
            {
                table.PrimaryKey("PK_TvShows", x => x.Id);
            });

        migrationBuilder.CreateTable(
            name: "Episodes",
            columns: table => new
            {
                Id = table.Column<long>(nullable: false)
                    .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
                BroadcastDate = table.Column<DateTime>(nullable: true),
                Duration = table.Column<TimeSpan>(nullable: true),
                Number = table.Column<int>(nullable: true),
                Season = table.Column<string>(nullable: true),
                Title = table.Column<string>(nullable: true),
                TvShowId = table.Column<long>(nullable: false)
            },
            constraints: table =>
            {
                table.PrimaryKey("PK_Episodes", x => x.Id);
                table.ForeignKey(
                    name: "FK_Episodes_TvShows_TvShowId",
                    column: x => x.TvShowId,
                    principalTable: "TvShows",
                    principalColumn: "Id",
                    onDelete: ReferentialAction.Cascade);
            });

        migrationBuilder.CreateTable(
            name: "Subscriptions",
            columns: table => new
            {
                TvShowId = table.Column<long>(nullable: false),
                UserId = table.Column<Guid>(nullable: false)
            },
            constraints: table =>
            {
                table.PrimaryKey("PK_Subscriptions", x => new { x.TvShowId, x.UserId });
                table.ForeignKey(
                    name: "FK_Subscriptions_TvShows_TvShowId",
                    column: x => x.TvShowId,
                    principalTable: "TvShows",
                    principalColumn: "Id",
                    onDelete: ReferentialAction.Cascade);
                table.ForeignKey(
                    name: "FK_Subscriptions_AspNetUsers_UserId",
                    column: x => x.UserId,
                    principalTable: "AspNetUsers",
                    principalColumn: "Id",
                    onDelete: ReferentialAction.Cascade);
            });

        migrationBuilder.CreateTable(
            name: "TvShowGenre",
            columns: table => new
            {
                TvShowId = table.Column<long>(nullable: false),
                GenreId = table.Column<long>(nullable: false)
            },
            constraints: table =>
            {
                table.PrimaryKey("PK_TvShowGenre", x => new { x.TvShowId, x.GenreId });
                table.ForeignKey(
                    name: "FK_TvShowGenre_Genres_GenreId",
                    column: x => x.GenreId,
                    principalTable: "Genres",
                    principalColumn: "Id",
                    onDelete: ReferentialAction.Cascade);
                table.ForeignKey(
                    name: "FK_TvShowGenre_TvShows_TvShowId",
                    column: x => x.TvShowId,
                    principalTable: "TvShows",
                    principalColumn: "Id",
                    onDelete: ReferentialAction.Cascade);
            });

        migrationBuilder.CreateIndex(
            name: "UserNameIndex",
            table: "AspNetUsers",
            column: "NormalizedUserName",
            unique: true,
            filter: "[NormalizedUserName] IS NOT NULL");

        migrationBuilder.CreateIndex(
            name: "RoleNameIndex",
            table: "AspNetRoles",
            column: "NormalizedName",
            unique: true,
            filter: "[NormalizedName] IS NOT NULL");

        migrationBuilder.CreateIndex(
            name: "IX_Episodes_TvShowId",
            table: "Episodes",
            column: "TvShowId");

        migrationBuilder.CreateIndex(
            name: "IX_Notifications_UserId",
            table: "Notifications",
            column: "UserId");

        migrationBuilder.CreateIndex(
            name: "IX_Subscriptions_UserId",
            table: "Subscriptions",
            column: "UserId");

        migrationBuilder.CreateIndex(
            name: "IX_TvShowGenre_GenreId",
            table: "TvShowGenre",
            column: "GenreId");

        migrationBuilder.AddForeignKey(
            name: "FK_AspNetUserTokens_AspNetUsers_UserId",
            table: "AspNetUserTokens",
            column: "UserId",
            principalTable: "AspNetUsers",
            principalColumn: "Id",
            onDelete: ReferentialAction.Cascade);
    }
}

5 ответов

В новой миграции просто отбросьте ключи перед изменением столбцов и затем снова добавьте те же ключи.

protected override void Up(MigrationBuilder migrationBuilder)
{
    migrationBuilder.DropPrimaryKey("PK_AspNetUserTokens", "AspNetUserTokens");
    migrationBuilder.DropPrimaryKey("PK_AspNetUserLogins", "AspNetUserLogins");
        
    ...
    migrationBuilder.AlterColumn<string>(...);
    ...

    migrationBuilder.AddPrimaryKey("PK_AspNetUserTokens", "AspNetUserTokens", new string[] { "UserId", "LoginProvider", "Name" });
    migrationBuilder.AddPrimaryKey("PK_AspNetUserLogins", "AspNetUserLogins", new string[] { "LoginProvider", "ProviderKey" });
}

Я столкнулся с той же проблемой, что и вы. Я удалил свою папку "Миграция" и снова добавил миграцию. Из-за предыдущих изменений миграции не удалось создать FK соответственно.

Я столкнулся с этой ошибкой при изменении схемы идентификации DbContext. После проверки AspNetUserTokensтаблица имеет ПК, состоящий из 3 столбцов. Я сделал следующее обходное решение:

Отбросьте ПК AspNetUserTokens:

ALTER TABLE AspNetUserTokens DROP CONSTRAINT PK_AspNetUserTokens

Вы можете снова столкнуться с этой ошибкой AspNetUserLogins, так же и для этой таблицы:

ALTER TABLE AspNetUserLogins DROP CONSTRAINT PK_AspNetUserLogins

потом update-database надеюсь, это Done.

Наконец, добавьте обратно PK:

ALTER TABLE AspNetUserLogins ADD CONSTRAINT PK_AspNetUserLogins PRIMARY KEY (LoginProvider,ProviderKey)
ALTER TABLE AspNetUserTokens ADD CONSTRAINT PK_AspNetUserTokens PRIMARY KEY ([UserId],[LoginProvider],[Name])

Вы должны откатить миграции до последнего успеха. использование dotnet ef migrations remove Команда для каждой неудачной миграции.

У меня была та же ошибка, но для другой таблицы и столбцов моя ошибка была следующей: объект «PK_AspNetUserTokens» зависит от столбца «LoginProvider».

Я не уверен, что это правильный способ сделать это при миграции, но у меня это сработало.

Я переместилmigrationBuilder.AlterColumn<string>("LoginProvidertable: "AspNetUserLogins",вышеmigrationBuilder.AlterColumn<string>("Name","AspNetUserTokens

Сделал это для обоихUpиDownметоды миграции, поскольку я подозревал, что при миграции таблица и столбец могут зависеть от нее в пакетном задании.

Также стоит отметить: у меня не было ограничений ни в одной из таблиц, поэтому в старых миграциях могло быть что-то, вызывающее это.

Другие вопросы по тегам