Identity 2.0 添加额外的电子邮件列

Identity 2.0 Adding extra Email column

当我尝试登录我的开发站点时,出现一个奇怪的错误:

Invalid column name 'Email1'.

我已经为许多不同的 ASP.NET Identity 2.0 classes 派生了 classes,即:

public class MyUser : IdentityUser<int, MyLogin, MyUserRole, MyClaim>//, IUser<int>
{
    #region properties

    public string ActivationToken { get; set; }

    public string PasswordAnswer { get; set; }

    public string PasswordQuestion { get; set; }

    public string FirstName { get; set; }

    public string LastName { get; set; }

    public string TaxID { get; set; }

    public bool IsActive { get; set; }

    public bool IsApproved { get; set; }

    #endregion

    #region methods

    public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<MyUser, int> userManager)
    {
        var userIdentity = await userManager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
        // Add custom user claims here
        return userIdentity;
    }

    #endregion
}

违规代码在 AccountController 的登录方法中对 UserManager.FindAsync() 的调用中:

public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
    {
        if (ModelState.IsValid)
        {
            var user = await UserManager.FindAsync(model.Email, model.Password);
            if (user != null)
            {
                await SignInAsync(user, model.RememberMe);
                return RedirectToLocal(returnUrl);
            }
            ModelState.AddModelError("", "Invalid username or password.");
        }

        // If we got this far, something failed, redisplay form
        return View(model);
    }

我这样设计我的用户 table:

CREATE TABLE [dbo].[User]
(
    [ID] [int] IDENTITY(1,1) NOT NULL,
    [Password] [nvarchar](50) NOT NULL,
    [FirstName] [nvarchar](50) NULL,
    [LastName] [nvarchar](50) NULL,
    [Email] [nvarchar](50) NOT NULL,
    [TaxID] [nvarchar](50) NULL,
    [PaymentMethodID] [int] NULL,
    [IsActive] [bit] NOT NULL DEFAULT 1,
    [IsApproved] [bit] NOT NULL,
    [IsLocked] [bit] NOT NULL,
    [CreationDate] [datetime] NULL,
    [ApprovalDate] [datetime] NULL DEFAULT NULL,
    [LastLoginDate] [datetime] NULL,
    [PasswordQuestion] [nvarchar](max) NULL,
    [PasswordAnswer] [nvarchar](max) NULL,
    [ActivationToken] [nvarchar](200) NULL,
    [EmailConfirmed] [bit] NOT NULL,
    [SecurityStamp] [nvarchar](max) NULL,
    [PhoneNumber] [nvarchar](50) NULL,
    [PhoneNumberConfirmed] [bit] NOT NULL,
    [TwoFactorEnabled] [bit] NOT NULL,
    [LockoutEndDateUtc] [datetime2](7) NULL,
    [LockoutEnabled] [bit] NOT NULL,
    [AccessFailedCount] [int] NOT NULL,
    CONSTRAINT [User_PK] PRIMARY KEY NONCLUSTERED ([ID]),
    CONSTRAINT [Email_UK] UNIQUE NONCLUSTERED([Email])
)

我在 MyDbContext 的 OnModelCreating 方法中将我的 MyUser class 绑定到 table:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);
            // Map Entities to their tables.
            modelBuilder.Entity<MyUser>().ToTable("User");
            modelBuilder.Entity<MyRole>().ToTable("Role");
            modelBuilder.Entity<MyClaim>().ToTable("UserClaim");
            modelBuilder.Entity<MyLogin>().ToTable("UserLogin");
            modelBuilder.Entity<MyUserRole>().ToTable("UserRole");
            // Set AutoIncrement-Properties
            modelBuilder.Entity<MyUser>().Property(r => r.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
            modelBuilder.Entity<MyClaim>().Property(r => r.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
            modelBuilder.Entity<MyRole>().Property(r => r.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
            // Override some column mappings that do not match our default
            modelBuilder.Entity<MyUser>().Property(r => r.UserName).HasColumnName("Email");
            modelBuilder.Entity<MyUser>().Property(r => r.PasswordHash).HasColumnName("Password");
        }

某处 Identity 2.0 正在创建另一个不应创建的电子邮件列。有什么想法吗?

默认架构中已经有名称为 Email 的列。

正如@enki.dev 在他删除的答案中建议的那样,如果您查看 IdentityUser 的定义,您已经定义了这些属性。

你在这里做的事情很危险:

modelBuilder.Entity<MyUser>().Property(r => r.UserName).HasColumnName("Email");
modelBuilder.Entity<MyUser>().Property(r => r.PasswordHash).HasColumnName("Password");

当您试图将一列强制插入另一列时。 属性 电子邮件已在此框架中广泛用于密码检索等。

您可以尝试重命名它

modelBuilder.Entity<MyUser>().Property(r => r.Email).HasColumnName("Blah");

所以你不会有重复的;但我猜你会在途中遇到许多其他问题。

为什么不直接将电子邮件存储在 UserName 属性 中?

另一个建议;最好让框架使用迁移为您创建表,这样您就可以始终知道发生了什么。

从 Visual Studio 选择菜单

  • 工具 - NuGet Packager Manager - 包管理器控制台

select 您在组合中的项目:默认项目。

运行 Enable-Migrations.

它应该创建一个名为 Migrations 的文件夹,其中包含一个名为 Configuration.cs.

的文件

构造函数应如下所示:

public Configuration()
{
    AutomaticMigrationsEnabled = false;
}

将值 AutomaticMigrationsEnabled 更改为 true

回到Package Manager Console和运行

Update-Database

Update-Database -Force

为您的表重新创建整个架构。

那里有一个受保护的方法,您可以在其中查看您的数据:

protected override void Seed(ASPNETIdentity2.Models.MyContext context)
{
    //  This method will be called after migrating to the latest version.

    //  You can use the DbSet<T>.AddOrUpdate() helper extension method 
    //  to avoid creating duplicate seed data. E.g.
    //
    //    context.People.AddOrUpdate(
    //      p => p.FullName,
    //      new Person { FullName = "Andrew Peters" },
    //      new Person { FullName = "Brice Lambson" },
    //      new Person { FullName = "Rowan Miller" }
    //    );
    //
}