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