Migrating to Asp.Net Identity 2.0: new columns not

2019-03-20 14:48发布

问题:

I get the following error when I try to register a new user, using Identity 2.0 and the default MVC 5 application:

Invalid column name 'Email'.
Invalid column name 'EmailConfirmed'.
Invalid column name 'PhoneNumber'.
Invalid column name 'PhoneNumberConfirmed'.
Invalid column name 'TwoFactorEnabled'.
Invalid column name 'LockoutEndDateUtc'.
Invalid column name 'LockoutEnabled'.
Invalid column name 'AccessFailedCount'.
(repeats 2 more times, I have a total of 4 test users in AspNetUsers table.)

I have a small application I've just upgraded from MVC4/Identity 1.0 to MVC5/Identity 2.0, so I had the Identity 1.0 columns (UserName, PasswordHash, SecurityStamp, Discriminator) working.

  • I'm was using a remotely hosted SQL2012 DB with the standard Identity 1.0 tables.
  • I created a 'clean' project, registered a user and it ran fine on the localDB.
  • I successfully ran 'add-migration initial' and 'update-database' on my remote database.
  • I initially followed this official guide , and the code in step 5 wasn't being generated. I tried pasting it in by hand and ran "update-database -verbose" again. Seemed to complete successfully, but still get the error.

Appreciate any help!

migration and configuration.cs files

internal sealed class Configuration : DbMigrationsConfiguration<FactBanker.Models.ApplicationDbContext>
{
    public Configuration()
    {
        AutomaticMigrationsEnabled = true;
    }

    protected override void Seed(FactBanker.Models.ApplicationDbContext context)
    {

    }
}

}

My V023 migration.cs file Both the Up() and Down() methods were empty.

public partial class V023 : DbMigration
{
    public override void Up()
    {

    }

    public override void Down()
    {

    }
}

回答1:

I was having the same problem. I used this manual migration and I haven't run into any additional issues yet.

public override void Up()
{
    RenameColumn(table: "dbo.AspNetUserClaims", name: "User_Id", newName: "UserId");
    RenameIndex(table: "dbo.AspNetUserClaims", name: "IX_User_Id", newName: "IX_UserId");
    DropPrimaryKey("dbo.AspNetUserLogins");
    AddColumn("dbo.AspNetUsers", "Email", c => c.String(maxLength: 256));
    AddColumn("dbo.AspNetUsers", "EmailConfirmed", c => c.Boolean(nullable: false));
    AddColumn("dbo.AspNetUsers", "PhoneNumber", c => c.String()); 
    AddColumn("dbo.AspNetUsers", "PhoneNumberConfirmed", c => c.Boolean(nullable: false));
    AddColumn("dbo.AspNetUsers", "TwoFactorEnabled", c => c.Boolean(nullable: false));
    AddColumn("dbo.AspNetUsers", "LockoutEndDateUtc", c => c.DateTime());
    AddColumn("dbo.AspNetUsers", "LockoutEnabled", c => c.Boolean(nullable: false));
    AddColumn("dbo.AspNetUsers", "AccessFailedCount", c => c.Int(nullable: false));
    AlterColumn("dbo.AspNetUsers", "UserName", c => c.String(nullable: false, maxLength: 256));
    AlterColumn("dbo.AspNetUsers", "FirstName", c => c.String(nullable: false));
    AlterColumn("dbo.AspNetUsers", "LastName", c => c.String(nullable: false));
    AddColumn("dbo.AspNetUsers", "CreatedDateTime", c => c.DateTime(nullable: false));
    AlterColumn("dbo.AspNetRoles", "Name", c => c.String(nullable: false, maxLength: 256));
    AddPrimaryKey("dbo.AspNetUserLogins", new[] { "LoginProvider", "ProviderKey", "UserId" });
    CreateIndex("dbo.AspNetUsers", "UserName", unique: true, name: "UserNameIndex");
    CreateIndex("dbo.AspNetRoles", "Name", unique: true, name: "RoleNameIndex");
    DropColumn("dbo.AspNetUsers", "Discriminator");
} 

Taken from: http://adamstephensen.com/2014/05/02/upgrading-from-asp-net-identity-1-0-to-2-0/



回答2:

The reason is you've upgraded to Microsoft.AspNet.Identity.EntityFramework 2.0.0.0 and that changes the user context.

To fix either generate a new db (set a new connection string mdf file) or change the sql table.



回答3:

I had the same problem. Based on what Dan Gershony said, I simply uninstalled the Microsoft.AspNet.Identity.EntityFramework 2.0.0.0 and install an older version like Microsoft.AspNet.Identity.EntityFramework -Version 1.0.0. This solved my problem.



回答4:

Tried the solution proposed by user1502551 but it gave me issues and didn't include the Down() method. The problems I was having was that the indexes being altered didn't exist by default from Identity 1.0 and there were a couple of extra columns that 2.0/2.1 doesn't expect (namely First and Last Name fields). Full Up() and Down() here:

public override void Up()
    {
        RenameColumn(table: "dbo.AspNetUserClaims", name: "User_Id", newName: "UserId");
        AddColumn("dbo.AspNetUsers", "Email", c => c.String());
        AddColumn("dbo.AspNetUsers", "EmailConfirmed", c => c.Boolean(nullable: false));
        AddColumn("dbo.AspNetUsers", "PhoneNumber", c => c.String());
        AddColumn("dbo.AspNetUsers", "PhoneNumberConfirmed", c => c.Boolean(nullable: false));
        AddColumn("dbo.AspNetUsers", "TwoFactorEnabled", c => c.Boolean(nullable: false));
        AddColumn("dbo.AspNetUsers", "LockoutEndDateUtc", c => c.DateTime());
        AddColumn("dbo.AspNetUsers", "LockoutEnabled", c => c.Boolean(nullable: false));
        AddColumn("dbo.AspNetUsers", "AccessFailedCount", c => c.Int(nullable: false));
        AlterColumn("dbo.AspNetUsers", "UserName", c => c.String(nullable: false));
        DropColumn("dbo.AspNetUsers", "Discriminator");
    }

    public override void Down()
    {
        AddColumn("dbo.AspNetUsers", "Discriminator", c => c.String(nullable: false, maxLength: 128));
        AlterColumn("dbo.AspNetUsers", "UserName", c => c.String(nullable: true));
        DropColumn("dbo.AspNetUsers", "AccessFailedCount");
        DropColumn("dbo.AspNetUsers", "LockoutEnabled");
        DropColumn("dbo.AspNetUsers", "LockoutEndDateUtc");
        DropColumn("dbo.AspNetUsers", "TwoFactorEnabled");
        DropColumn("dbo.AspNetUsers", "PhoneNumberConfirmed");
        DropColumn("dbo.AspNetUsers", "PhoneNumber");
        DropColumn("dbo.AspNetUsers", "EmailConfirmed");
        DropColumn("dbo.AspNetUsers", "Email");
        RenameColumn(table: "dbo.AspNetUserClaims", name: "UserId", newName: "User_Id");
    }


回答5:

You have to modify all the entities that have been updated in version 2.0, for example:

public partial class AspNetUser
{    
    public AspNetUser()
    {
        AspNetUserClaims = new HashSet<AspNetUserClaim>();
        AspNetUserLogins = new HashSet<AspNetUserLogin>();
        AspNetRoles = new HashSet<AspNetRole>();
    }

    public string Id { get; set; }

    [StringLength(256)]
    public string UserName { get; set; }

    public string PasswordHash { get; set; }

    public string SecurityStamp { get; set; }

    [MaxLength(256)]
    public string Email { get; set; }

    public bool EmailConfirmed { get; set; }

    public string PhoneNumber { get; set; }

    public bool PhoneNumberConfirmed { get; set; }

    public bool TwoFactorEnabled { get; set; }

    public DateTime LockoutEndDateUtc { get; set; }

    public bool LockoutEnabled { get; set; }

    public int AccessFailedCount { get; set; }

    public int UserId { get; set; }

    public virtual ICollection<AspNetUserClaim> AspNetUserClaims { get; set; }

    public virtual ICollection<AspNetUserLogin> AspNetUserLogins { get; set; }

    public virtual User User { get; set; }

    public virtual ICollection<AspNetRole> AspNetRoles { get; set; }
}

public partial class AspNetUserClaim
{
    [Key]
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }

    public string ClaimType { get; set; }

    public string ClaimValue { get; set; }

    [Required]
    [StringLength(128)]
    public string UserId { get; set; }

    public virtual AspNetUser AspNetUser { get; set; }
}

You also need to modify mappings of the entities that changed in the OnModelCreating method of your dbcontext, After this you can add your migration



回答6:

Are you sure you got the correct User class in your Dbcontext? If you want to modify your User table you should inhert like this:

public class ApplicationDbContext : IdentityDbContext<MyCustomUserClass>
{
    ...
}

and don t put anything like:

public DbSet<MyCustomUserClass> Users { get; set; }

in there since it will already happen in the base class.