Skip to content

Primary Keys mangled on generic DbSets models after second migration #3545

Description

@TsengSR

The migration file (i.e. 20151024123838_Init.cs) gets mangled primary keys on second migration.

I am using AspNet Identity in my project and after the initial migration the 2nd (and following) migrations will mangle the primary keys, basically making it impossible to migrate further and having to wipe of the database after each change in the structure.

For example:

public class AuthUser : IdentityUser<Guid>
{
    public AuthUser() { }
    public AuthUser(string userName) : base(userName) { }

    public string FirstName { get; set; }
    public string LastName { get; set; }
}
public class AuthRole : IdentityRole<Guid>
{
    public AuthRole() { }
    public AuthRole(string roleName) : base(roleName) { }
}

public class AuthContext : IdentityDbContext<AuthUser, AuthRole, Guid>
{
}

After setting up the initial project, run a migration

dnx ef migrations add Init

The files genreated are generated correctly. Without further change, add a second migration

dnx ef migrations add Init2

The Init2 file (i.e.20151024123846_Init2.cs) has mangled primary keys:

First imgration (20151024123838_Init.cs):

public partial class Init : Migration
{
    protected override void Up(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.CreateTable(
            name: "AspNetRoles",
            columns: table => new
            {
                Id = table.Column<Guid>(nullable: false),
                ConcurrencyStamp = table.Column<string>(nullable: true),
                Name = table.Column<string>(nullable: true),
                NormalizedName = table.Column<string>(nullable: true)
            },
            constraints: table =>
            {
                table.PrimaryKey("PK_AuthRole", x => x.Id);
            });
        migrationBuilder.CreateTable(
            name: "AspNetUsers",
            columns: table => new
            {
                Id = table.Column<Guid>(nullable: false),
                AccessFailedCount = table.Column<int>(nullable: false),
                ConcurrencyStamp = table.Column<string>(nullable: true),
                DisplayName = table.Column<string>(nullable: true),
                Domain = table.Column<string>(nullable: true),
                DomainUsername = table.Column<string>(nullable: true),
                Email = table.Column<string>(nullable: true),
                EmailConfirmed = table.Column<bool>(nullable: false),
                FirstName = table.Column<string>(nullable: true),
                IsDomainUser = table.Column<bool>(nullable: false),
                LastName = table.Column<string>(nullable: true),
                LockoutEnabled = table.Column<bool>(nullable: false),
                LockoutEnd = table.Column<DateTimeOffset>(nullable: true),
                NormalizedEmail = table.Column<string>(nullable: true),
                NormalizedUserName = table.Column<string>(nullable: true),
                PasswordHash = table.Column<string>(nullable: true),
                PhoneNumber = table.Column<string>(nullable: true),
                PhoneNumberConfirmed = table.Column<bool>(nullable: false),
                SecurityStamp = table.Column<string>(nullable: true),
                TwoFactorEnabled = table.Column<bool>(nullable: false),
                UserName = table.Column<string>(nullable: true)
            },
            constraints: table =>
            {
                table.PrimaryKey("PK_AuthUser", x => x.Id);
            });
        migrationBuilder.CreateTable(
            name: "Application",
            columns: table => new
            {
                ApplicationID = table.Column<string>(nullable: false),
                DisplayName = table.Column<string>(nullable: true),
                LogoutRedirectUri = table.Column<string>(nullable: true),
                RedirectUri = table.Column<string>(nullable: true),
                Secret = table.Column<string>(nullable: true),
                Type = table.Column<int>(nullable: false)
            },
            constraints: table =>
            {
                table.PrimaryKey("PK_Application", x => x.ApplicationID);
            });
        migrationBuilder.CreateTable(
            name: "AspNetRoleClaims",
            columns: table => new
            {
                Id = table.Column<int>(nullable: false)
                    .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
                ClaimType = table.Column<string>(nullable: true),
                ClaimValue = table.Column<string>(nullable: true),
                RoleId = table.Column<Guid>(nullable: false)
            },
            constraints: table =>
            {
                table.PrimaryKey("PK_IdentityRoleClaim<Guid>", x => x.Id);
                table.ForeignKey(
                    name: "FK_IdentityRoleClaim<Guid>_AuthRole_RoleId",
                    column: x => x.RoleId,
                    principalTable: "AspNetRoles",
                    principalColumn: "Id",
                    onDelete: ReferentialAction.Cascade);
            });
        migrationBuilder.CreateTable(
            name: "AspNetUserClaims",
            columns: table => new
            {
                Id = table.Column<int>(nullable: false)
                    .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
                ClaimType = table.Column<string>(nullable: true),
                ClaimValue = table.Column<string>(nullable: true),
                UserId = table.Column<Guid>(nullable: false)
            },
            constraints: table =>
            {
                table.PrimaryKey("PK_IdentityUserClaim<Guid>", x => x.Id);
                table.ForeignKey(
                    name: "FK_IdentityUserClaim<Guid>_AuthUser_UserId",
                    column: x => x.UserId,
                    principalTable: "AspNetUsers",
                    principalColumn: "Id",
                    onDelete: ReferentialAction.Cascade);
            });
        migrationBuilder.CreateTable(
            name: "AspNetUserLogins",
            columns: table => new
            {
                LoginProvider = table.Column<string>(nullable: false),
                ProviderKey = table.Column<string>(nullable: false),
                ProviderDisplayName = table.Column<string>(nullable: true),
                UserId = table.Column<Guid>(nullable: false)
            },
            constraints: table =>
            {
                table.PrimaryKey("PK_IdentityUserLogin<Guid>", x => new { x.LoginProvider, x.ProviderKey });
                table.ForeignKey(
                    name: "FK_IdentityUserLogin<Guid>_AuthUser_UserId",
                    column: x => x.UserId,
                    principalTable: "AspNetUsers",
                    principalColumn: "Id",
                    onDelete: ReferentialAction.Cascade);
            });
        migrationBuilder.CreateTable(
            name: "AspNetUserRoles",
            columns: table => new
            {
                UserId = table.Column<Guid>(nullable: false),
                RoleId = table.Column<Guid>(nullable: false)
            },
            constraints: table =>
            {
                table.PrimaryKey("PK_IdentityUserRole<Guid>", x => new { x.UserId, x.RoleId });
                table.ForeignKey(
                    name: "FK_IdentityUserRole<Guid>_AuthRole_RoleId",
                    column: x => x.RoleId,
                    principalTable: "AspNetRoles",
                    principalColumn: "Id",
                    onDelete: ReferentialAction.Cascade);
                table.ForeignKey(
                    name: "FK_IdentityUserRole<Guid>_AuthUser_UserId",
                    column: x => x.UserId,
                    principalTable: "AspNetUsers",
                    principalColumn: "Id",
                    onDelete: ReferentialAction.Cascade);
            });
        migrationBuilder.CreateIndex(
            name: "RoleNameIndex",
            table: "AspNetRoles",
            column: "NormalizedName");
        migrationBuilder.CreateIndex(
            name: "EmailIndex",
            table: "AspNetUsers",
            column: "NormalizedEmail");
        migrationBuilder.CreateIndex(
            name: "UserNameIndex",
            table: "AspNetUsers",
            column: "NormalizedUserName");
    }

    protected override void Down(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.DropTable("AspNetRoleClaims");
        migrationBuilder.DropTable("AspNetUserClaims");
        migrationBuilder.DropTable("AspNetUserLogins");
        migrationBuilder.DropTable("AspNetUserRoles");
        migrationBuilder.DropTable("Application");
        migrationBuilder.DropTable("AspNetRoles");
        migrationBuilder.DropTable("AspNetUsers");
    }
}

Second, mangeld migration (20151024123846_Init2.cs):

public partial class Init2 : Migration
{
    protected override void Up(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.DropForeignKey(name: "FK_Guid>_AuthRole_RoleId", table: "AspNetRoleClaims");
        migrationBuilder.DropForeignKey(name: "FK_Guid>_AuthUser_UserId", table: "AspNetUserClaims");
        migrationBuilder.DropForeignKey(name: "FK_Guid>_AuthUser_UserId", table: "AspNetUserLogins");
        migrationBuilder.DropForeignKey(name: "FK_Guid>_AuthRole_RoleId", table: "AspNetUserRoles");
        migrationBuilder.DropForeignKey(name: "FK_Guid>_AuthUser_UserId", table: "AspNetUserRoles");
        migrationBuilder.DropPrimaryKey(name: "PK_Guid>", table: "AspNetUserRoles");
        migrationBuilder.DropPrimaryKey(name: "PK_Guid>", table: "AspNetUserLogins");
        migrationBuilder.DropPrimaryKey(name: "PK_Guid>", table: "AspNetUserClaims");
        migrationBuilder.DropPrimaryKey(name: "PK_Guid>", table: "AspNetRoleClaims");
        migrationBuilder.AddPrimaryKey(
            name: "PK_IdentityUserRole<Guid>",
            table: "AspNetUserRoles",
            columns: new[] { "UserId", "RoleId" });
        migrationBuilder.AddPrimaryKey(
            name: "PK_IdentityUserLogin<Guid>",
            table: "AspNetUserLogins",
            columns: new[] { "LoginProvider", "ProviderKey" });
        migrationBuilder.AddPrimaryKey(
            name: "PK_IdentityUserClaim<Guid>",
            table: "AspNetUserClaims",
            column: "Id");
        migrationBuilder.AddPrimaryKey(
            name: "PK_IdentityRoleClaim<Guid>",
            table: "AspNetRoleClaims",
            column: "Id");
        migrationBuilder.AddForeignKey(
            name: "FK_IdentityRoleClaim<Guid>_AuthRole_RoleId",
            table: "AspNetRoleClaims",
            column: "RoleId",
            principalTable: "AspNetRoles",
            principalColumn: "Id",
            onDelete: ReferentialAction.Cascade);
        migrationBuilder.AddForeignKey(
            name: "FK_IdentityUserClaim<Guid>_AuthUser_UserId",
            table: "AspNetUserClaims",
            column: "UserId",
            principalTable: "AspNetUsers",
            principalColumn: "Id",
            onDelete: ReferentialAction.Cascade);
        migrationBuilder.AddForeignKey(
            name: "FK_IdentityUserLogin<Guid>_AuthUser_UserId",
            table: "AspNetUserLogins",
            column: "UserId",
            principalTable: "AspNetUsers",
            principalColumn: "Id",
            onDelete: ReferentialAction.Cascade);
        migrationBuilder.AddForeignKey(
            name: "FK_IdentityUserRole<Guid>_AuthRole_RoleId",
            table: "AspNetUserRoles",
            column: "RoleId",
            principalTable: "AspNetRoles",
            principalColumn: "Id",
            onDelete: ReferentialAction.Cascade);
        migrationBuilder.AddForeignKey(
            name: "FK_IdentityUserRole<Guid>_AuthUser_UserId",
            table: "AspNetUserRoles",
            column: "UserId",
            principalTable: "AspNetUsers",
            principalColumn: "Id",
            onDelete: ReferentialAction.Cascade);
    }

    protected override void Down(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.DropForeignKey(name: "FK_IdentityRoleClaim<Guid>_AuthRole_RoleId", table: "AspNetRoleClaims");
        migrationBuilder.DropForeignKey(name: "FK_IdentityUserClaim<Guid>_AuthUser_UserId", table: "AspNetUserClaims");
        migrationBuilder.DropForeignKey(name: "FK_IdentityUserLogin<Guid>_AuthUser_UserId", table: "AspNetUserLogins");
        migrationBuilder.DropForeignKey(name: "FK_IdentityUserRole<Guid>_AuthRole_RoleId", table: "AspNetUserRoles");
        migrationBuilder.DropForeignKey(name: "FK_IdentityUserRole<Guid>_AuthUser_UserId", table: "AspNetUserRoles");
        migrationBuilder.DropPrimaryKey(name: "PK_IdentityUserRole<Guid>", table: "AspNetUserRoles");
        migrationBuilder.DropPrimaryKey(name: "PK_IdentityUserLogin<Guid>", table: "AspNetUserLogins");
        migrationBuilder.DropPrimaryKey(name: "PK_IdentityUserClaim<Guid>", table: "AspNetUserClaims");
        migrationBuilder.DropPrimaryKey(name: "PK_IdentityRoleClaim<Guid>", table: "AspNetRoleClaims");
        migrationBuilder.AddPrimaryKey(
            name: "PK_Guid>",
            table: "AspNetUserRoles",
            columns: new[] { "UserId", "RoleId" });
        migrationBuilder.AddPrimaryKey(
            name: "PK_Guid>",
            table: "AspNetUserLogins",
            columns: new[] { "LoginProvider", "ProviderKey" });
        migrationBuilder.AddPrimaryKey(
            name: "PK_Guid>",
            table: "AspNetUserClaims",
            column: "Id");
        migrationBuilder.AddPrimaryKey(
            name: "PK_Guid>",
            table: "AspNetRoleClaims",
            column: "Id");
        migrationBuilder.AddForeignKey(
            name: "FK_Guid>_AuthRole_RoleId",
            table: "AspNetRoleClaims",
            column: "RoleId",
            principalTable: "AspNetRoles",
            principalColumn: "Id",
            onDelete: ReferentialAction.Restrict);
        migrationBuilder.AddForeignKey(
            name: "FK_Guid>_AuthUser_UserId",
            table: "AspNetUserClaims",
            column: "UserId",
            principalTable: "AspNetUsers",
            principalColumn: "Id",
            onDelete: ReferentialAction.Restrict);
        migrationBuilder.AddForeignKey(
            name: "FK_Guid>_AuthUser_UserId",
            table: "AspNetUserLogins",
            column: "UserId",
            principalTable: "AspNetUsers",
            principalColumn: "Id",
            onDelete: ReferentialAction.Restrict);
        migrationBuilder.AddForeignKey(
            name: "FK_Guid>_AuthRole_RoleId",
            table: "AspNetUserRoles",
            column: "RoleId",
            principalTable: "AspNetRoles",
            principalColumn: "Id",
            onDelete: ReferentialAction.Restrict);
        migrationBuilder.AddForeignKey(
            name: "FK_Guid>_AuthUser_UserId",
            table: "AspNetUserRoles",
            column: "UserId",
            principalTable: "AspNetUsers",
            principalColumn: "Id",
            onDelete: ReferentialAction.Restrict);
    }
}

The dnx ef database update will now of course fail.

As you can see "FK_IdentityRoleClaim_AuthRole_RoleId" got mangled into "FK_Guid>_AuthRole_RoleId" and the "IdentityRoleClaim<" was removed.

It's a big game breaker, as migrations stop working when generic models are used.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions