迁移到 Asp.Net Identity 2.0:未在 AspNetUsers 表中创建新列

Posted

技术标签:

【中文标题】迁移到 Asp.Net Identity 2.0:未在 AspNetUsers 表中创建新列【英文标题】:Migrating to Asp.Net Identity 2.0: new columns not being created in AspNetUsers table 【发布时间】:2014-05-14 02:11:04 【问题描述】:

当我尝试使用 Identity 2.0 和默认的 MVC 5 应用程序注册新用户时出现以下错误:

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.)

我有一个小型应用程序,我刚刚从 MVC4/Identity 1.0 升级到 MVC5/Identity 2.0,所以我的 Identity 1.0 列(UserName、PasswordHash、SecurityStamp、Discriminator)正常工作。

我正在使用带有标准 Identity 1.0 表的远程托管 SQL2012 数据库。 我创建了一个“干净”的项目,注册了一个用户,它在 localDB 上运行良好。 我在远程数据库上成功运行了“add-migration initial”和“update-database”。 我最初关注的是 this official guide ,但没有生成步骤 5 中的代码。我尝试手动粘贴它并再次运行“update-database -verbose”。似乎成功完成,但仍然收到错误。

感谢任何帮助!

迁移和配置.cs 文件

internal sealed class Configuration : DbMigrationsConfiguration<FactBanker.Models.ApplicationDbContext>

    public Configuration()
    
        AutomaticMigrationsEnabled = true;
    

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

    

我的 V023 migration.cs 文件 Up() 和 Down() 方法都是空的。

public partial class V023 : DbMigration

    public override void Up()
    

    

    public override void Down()
    

    

【问题讨论】:

您提到的指南没有完整的迁移信息,那里缺少多个列...当您运行add-migration 时,它是否创建了迁移脚本?你能分享你的configuration.cs[whatever]_initial.cs吗? 很高兴知道,谢谢。我已经添加了上述文件,并且正在寻找描述完整 Identity 2.0 架构的内容。 您是否在运行 add-migration 和 update-database 之前尝试关闭自动迁移AutomaticMigrationsEnabled = false 是的,实际上我后来把它变成了真的。我只是将其更改为 false 并再次运行 add-migration/update-database,结果相同。欣赏这些想法。 【参考方案1】:

您确定您的 Dbcontext 中有正确的 User 类吗?如果你想修改你的用户表,你应该这样继承:

public class ApplicationDbContext : IdentityDbContext<MyCustomUserClass>

    ...

不要放类似的东西:

public DbSet<MyCustomUserClass> Users  get; set; 

在那里,因为它已经发生在基类中。

【讨论】:

感谢您的想法,但不,我根本没有修改或添加任何用户类。与我拥有的初始启动应用程序的唯一区别是我的数据库有其他表,这些表引用 aspnetusers 表中的 Id 列作为外键。我从这些表中删除了 FK 约束并再次运行 migrate/update,但没有任何区别。【参考方案2】:

原因是您已升级到 Microsoft.AspNet.Identity.EntityFramework 2.0.0.0 并且更改了用户上下文。

修复要么生成一个新的 db(设置一个新的连接字符串 mdf 文件)或更改 sql 表。

【讨论】:

感谢您的回复。这是对问题的一个很好的总结。但是,如果我手动更改表格,我认为这不能解决问题。使用 add-migration/update-database 应该更改表,这就是代码优先实体框架的重点。我暂时将其标记为答案,因为这是我见过的最接近的答案,现在我正在尝试的答案是完全放弃 EF 并通过实施我自己的 IUserStore 来实现我自己的数据访问层,odetocode.com/blogs/scott/archive/2013/11/25/… 相关文章在这里jskiles1.wordpress.com/2014/04/20/… 添加到 Dan Gershony 的答案:我向 SQL 添加了一个空白的新数据库,并将连接字符串指向这个新数据库。 Ran add-migration/Update-database 为标识 2.0 构建 aspNet 表。然后,我根据产生的更改使用新的列/名称更新了我的普通开发数据库。终于可以登录、验证等了。【参考方案3】:

我遇到了同样的问题。根据 Dan Gershony 所说,我只是卸载了 Microsoft.AspNet.Identity.EntityFramework 2.0.0.0 并安装了旧版本,如 Microsoft.AspNet.Identity.EntityFramework -Version 1.0.0。这解决了我的问题。

【讨论】:

这始终取决于您的需求,但请记住,2.0 修复了很多问题。【参考方案4】:

我遇到了同样的问题。我使用了这个手动迁移,还没有遇到任何其他问题。

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");
 

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

【讨论】:

我认为这可能是最接近的答案,没有尝试过,因为我已经改变了整体方法(完全摆脱了 EF)。不过看起来不错,谢谢。【参考方案5】:

尝试了 user1502551 提出的解决方案,但它给了我一些问题,并且没有包含 Down() 方法。我遇到的问题是,Identity 1.0 中默认情况下不存在被更改的索引,并且有几个 2.0/2.1 没有预料到的额外列(即名字和姓氏字段)。完整的 Up() 和 Down() 在这里:

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");
    

【讨论】:

【参考方案6】:

你必须修改所有在2.0版本中更新的实体,例如:

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; 

您还需要修改在您的 dbcontext 的 OnModelCreating 方法中更改的实体的映射,之后您可以添加您的迁移

【讨论】:

谢谢。从那时起,我就转向了 Azure B2C,所以我无法测试答案,但希望它可以帮助其他人。【参考方案7】:

我遇到了同样的错误。我所做的只是在 AspNetUser 中手动添加 LockoutEndDateUtc 列

【讨论】:

以上是关于迁移到 Asp.Net Identity 2.0:未在 AspNetUsers 表中创建新列的主要内容,如果未能解决你的问题,请参考以下文章

在 ASP.NET Identity 2.0 中获取当前用户 ID

Asp.net Identity 2.0 更新用户

Asp.net Core 2.0 Identity.TwoFactorRememberMe 到期

ASP.NET Identity 2.0 注销不起作用

ASP.NET Identity 2.0 解密 Owin cookie

Asp.NET Core 2.0 API 控制器中的 User.Identity.Name 为空