使用 ASP.NET Identity 时如何更改表名?

Posted

技术标签:

【中文标题】使用 ASP.NET Identity 时如何更改表名?【英文标题】:How can I change the table names when using ASP.NET Identity? 【发布时间】:2013-10-27 22:19:36 【问题描述】:

我正在使用 Visual Studio 2013 的发布版本(RTM,而不是 RC)(从 MSDN 2013-10-18 下载),因此是 AspNet.Identity 的最新 (RTM) 版本。当我创建一个新的 Web 项目时,我选择“个人用户帐户”进行身份验证。这将创建以下表格:

    AspNetRoles AspNetUserClaims AspNetUserLogins AspNetUserRoles AspNet 用户

当我注册一个新用户(使用默认模板)时,这些表(上面列出的)被创建,并且 AspNetUsers 表插入了一条记录,其中包含:

    身份证 用户名 密码哈希 安全印章 鉴别器

此外,通过向“ApplicationUser”类添加公共属性,我已成功向 AspNetUsers 表添加了其他字段,例如“FirstName”、“LastName”、“PhoneNumber”等。

这是我的问题。有没有办法更改上述表的名称(当它们首次创建时),或者它们是否总是以我上面列出的 AspNet 前缀命名?如果表名可以不同,请说明如何命名。

-- 更新--

我实现了@Hao Kung 的解决方案。它确实创建了一个新表(例如我称之为 MyUsers),但它仍然创建了 AspNetUsers 表。目标是用“MyUsers”表替换“AspNetUsers”表。请参阅下面的代码和创建的表的数据库图像。

我实际上想用我自己的名字替换每个 AspNet 表...对于 fxample、MyRoles、MyUserClaims、MyUserLogins、MyUserRoles 和 MyUsers。

我如何做到这一点并最终只得到一组表?

public class ApplicationUser : IdentityUser

    public string FirstName  get; set; 
    public string LastName  get; set; 
    public string Address1  get; set; 
    public string Address2  get; set; 
    public string City  get; set; 
    public string State  get; set; 
    public string PostalCode  get; set; 
    public string PhonePrimary  get; set; 
    public string PhoneSecondary  get; set; 


public class ApplicationDbContext : IdentityDbContext<ApplicationUser>

    public ApplicationDbContext(): base("DefaultConnection")
    
    

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    
        base.OnModelCreating(modelBuilder);
        modelBuilder.Entity<IdentityUser>().ToTable("MyUsers");
    

-- 更新答案--

感谢 Hao Kung 和 Peter Stulinski。这解决了我的问题...

    protected override void OnModelCreating(System.Data.Entity.DbModelBuilder modelBuilder)
    
        base.OnModelCreating(modelBuilder);

        modelBuilder.Entity<IdentityUser>().ToTable("MyUsers").Property(p => p.Id).HasColumnName("UserId");
        modelBuilder.Entity<ApplicationUser>().ToTable("MyUsers").Property(p => p.Id).HasColumnName("UserId");
        modelBuilder.Entity<IdentityUserRole>().ToTable("MyUserRoles");
        modelBuilder.Entity<IdentityUserLogin>().ToTable("MyUserLogins");
        modelBuilder.Entity<IdentityUserClaim>().ToTable("MyUserClaims");
        modelBuilder.Entity<IdentityRole>().ToTable("MyRoles");
    

【问题讨论】:

你确定吗?请删除您的所有表,删除您的 _migration 表,然后尝试。我在下面发布的与您的代码非常相似的代码不会创建 AspNetUsers 表。 您的代码和我的代码之间的唯一区别是我将 ApplicationUser 重命名为“User”。我的行为完全不同。在第一次创建时,它根据需要创建表并使用我指定的名称....也许只是为了“实验”尝试将 ApplicationUser 更改为 User 然后添加行 base.OnModelCreating(modelBuilder); modelBuilder.Entity() .ToTable("Users", "dbo"); modelBuilder.Entity() .ToTable("Users", "dbo"); 上面更新了解决方案... @Daskul Remove modelBuilder.Entity().ToTable("MyUsers").Property(p => p.Id).HasColumnName("UserId");在这种情况下,鉴别器列将不会添加到 MyUsers 表中。有关详细信息,请参阅此错误:***.com/questions/22054168/… @user2315985 - 您应该更新您的答案以删除包含@Sergey 提到的modelBuilder.Entity&lt;IdentityUser&gt;().ToTable("MyUsers").Property(p =&gt; p.Id).HasColumnName("UserId"); 的行。否则,正如@Daskul 指出的那样,新命名的MyUsers 表有一个鉴别器列。此外,@Matt 总体指出,您的 MyUserClaims 表结构将是错误的。我认为添加的想法来自@Giang 在msdn blog 中的评论,但这是错误的! 【参考方案1】:

仅出于文档目的,对于那些在未来几年来这篇文章的人(比如我 XD),放弃我评论的所有答案都是正确的,但是您可以使用 Alexandru Bucur 给出的这种方法来简化在他的博客上

         //But this method is not longer supported on netcore > 2.2, so I need to fix it
         foreach (var entityType in modelBuilder.Model.GetEntityTypes())
         
            var table = entityType.Relational().TableName;
             if (table.StartsWith("AspNet"))
             
                 entityType.Relational().TableName = table.Substring(6);
             
         ;

        //This is the functional way on NetCore > 2.2
        foreach (var entityType in modelBuilder.Model.GetEntityTypes())
        
            var tableName = entityType.GetTableName();
            if (tableName.StartsWith("AspNet"))
            
                entityType.SetTableName(tableName.Substring(6));
            
        

【讨论】:

当您想更改所有表名时,我认为这是一个很好的答案。我会在 SetTableName 方法中做一个非常小的更改并添加一个前缀,例如; entityType.SetTableName(newTableNamePrefix + tableName.Substring(6)); 也会有用的【参考方案2】:

但它在 .NET CORE (MVC 6) 中不起作用,因为我们需要将绑定更改为

喜欢

protected override void OnModelCreating(ModelBuilder builder)

    base.OnModelCreating(builder);

    builder.Entity<IdentityRole>().ToTable("Role");
    builder.Entity<IdentityUser>(entity => 
    
        entity.ToTable("User");
        entity.Property(p => p.Id).HasColumnName("UserId");
    );

它可能会帮助某人:)

【讨论】:

这对代码优先和数据库优先都有效吗? 我没有先尝试数据库,但我想如果模型和数据库相同,它应该可以工作。【参考方案3】:

您还可以创建配置类并指定每个身份类的每个细节,例如:

using System.Data.Entity.ModelConfiguration;

public class ApplicationUserConfig : EntityTypeConfiguration<ApplicationUser>

    public UserConfig()
    
        ToTable("Users");
        Property(u => u.LocationName).IsRequired();
    

然后在 OnModelCreating() 方法中包含这些配置:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
    
        base.OnModelCreating(modelBuilder);

        modelBuilder.Configurations.Add(new ApplicationUserConfig());
        ...
    

这将使您可以完全控制身份类的各个方面。

【讨论】:

【参考方案4】:

我们可以像这样更改 asp.net Identity 默认表名:

    public class ApplicationDbContext : IdentityDbContext
        
        public ApplicationDbContext(): base("DefaultConnection")
        
        

        protected override void OnModelCreating(System.Data.Entity.DbModelBuilder modelBuilder)
        
            base.OnModelCreating(modelBuilder);
            modelBuilder.Entity<IdentityUser>().ToTable("user");
            modelBuilder.Entity<ApplicationUser>().ToTable("user");

            modelBuilder.Entity<IdentityRole>().ToTable("role");
            modelBuilder.Entity<IdentityUserRole>().ToTable("userrole");
            modelBuilder.Entity<IdentityUserClaim>().ToTable("userclaim");
            modelBuilder.Entity<IdentityUserLogin>().ToTable("userlogin");
        
    

此外,我们可以扩展每个类并向类添加任何属性,例如“IdentityUser”、“IdentityRole”、...

    public class ApplicationRole : IdentityRole<string, ApplicationUserRole>

    public ApplicationRole() 
    
        this.Id = Guid.NewGuid().ToString();
    

    public ApplicationRole(string name)
        : this()
    
        this.Name = name;
    

    // Add any custom Role properties/code here



// Must be expressed in terms of our custom types:
public class ApplicationDbContext 
    : IdentityDbContext<ApplicationUser, ApplicationRole, 
    string, ApplicationUserLogin, ApplicationUserRole, ApplicationUserClaim>

    public ApplicationDbContext()
        : base("DefaultConnection")
    
    

    static ApplicationDbContext()
    
        Database.SetInitializer<ApplicationDbContext>(new ApplicationDbInitializer());
    

    public static ApplicationDbContext Create()
    
        return new ApplicationDbContext();
    

    // Add additional items here as needed

为了节省时间,我们可以使用AspNet Identity 2.0 Extensible Project Template 来扩展所有类。

【讨论】:

【参考方案5】:

以下是我的工作解决方案:

public class ApplicationDbContext : IdentityDbContext<ApplicationUser>

    public ApplicationDbContext()
        : base("DefaultConnection", throwIfV1Schema: false)
    
    

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    
        base.OnModelCreating(modelBuilder); // This needs to go before the other rules!

        modelBuilder.Entity<ApplicationUser>().ToTable("User");
        modelBuilder.Entity<IdentityRole>().ToTable("Role");
        modelBuilder.Entity<IdentityUserRole>().ToTable("UserRole");
        modelBuilder.Entity<IdentityUserClaim>().ToTable("UserClaim");
        modelBuilder.Entity<IdentityUserLogin>().ToTable("UserLogin");
    

    public static ApplicationDbContext Create()
    
        return new ApplicationDbContext();
    

详情请见this

【讨论】:

你能通过指定属性而不是(丑陋的)流利的 api 来做到这一点吗? 做了一个小的编辑,因为我设法否决了这个答案并且没有注意到!还更新了它以使用像这样的链接的首选方法[text](link) 我创建了一个空的 MVC 项目,运行了 1 次,创建了 asp 命名的表。然后我添加了这个小改动,删除了我所有的表和迁移文件夹(为了它的价值)并再次运行我的代码,但表拒绝被重命名。然后我创建了一个全新的项目,在运行之前进行了这个更改,现在它可以工作了。我是否遗漏了一些非常明显的东西??【参考方案6】:

您可以通过如下修改 IdentityModel.cs 轻松做到这一点:

在 DbContext 中覆盖 OnModelCreating 然后添加以下内容,这会将 AspNetUser 表更改为“Users”,您还可以更改字段名称,默认 Id 列将变为 User_Id。

modelBuilder.Entity<IdentityUser>()
                    .ToTable("Users", "dbo").Property(p => p.Id).HasColumnName("User_Id");

如果您想保留所有标准列名,则只需使用以下内容:

modelBuilder.Entity<IdentityUser>()
                        .ToTable("Users", "dbo")

下面的完整示例(这应该在您的 IdentityModel.cs 文件中)我将 ApplicationUser 类更改为 User。

public class User : IdentityUser
    
        public string PasswordOld  get; set; 
        public DateTime DateCreated  get; set; 

        public bool Activated  get; set; 

        public bool UserRole  get; set; 

    

public class ApplicationDbContext : IdentityDbContext<User>
    
        public ApplicationDbContext()
            : base("DefaultConnection")
        
        

        protected override void OnModelCreating(System.Data.Entity.DbModelBuilder modelBuilder)
        
            base.OnModelCreating(modelBuilder);
            modelBuilder.Entity<IdentityUser>()
                .ToTable("Users", "dbo").Property(p => p.Id).HasColumnName("User_Id");
            modelBuilder.Entity<User>()
                .ToTable("Users", "dbo").Property(p => p.Id).HasColumnName("User_Id");
        
    

请注意,如果当前表存在,我还没有设法让它工作。另请注意,您未映射默认列的任何列都将被创建。

希望对您有所帮助。

【讨论】:

要使这些更改生效,您需要使用迁移将更改推送到现有数据库。 如果你这样做,你的外键会有点奇怪,我认为你不需要更改 IdentityUser 上的表名。看到这个SO post 这就像一个额外的检查,因为这让我之前发现了。确保对 base.OnModelCreating 的调用是覆盖中的第一行代码,否则其余行将被基 Identity 类覆盖。 @DavidG 谢谢你 很好的解决方案。但不必覆盖 IdentityUser 的表名。请参阅此解决方案***.com/questions/28016684/…【参考方案7】:

您可以尝试在您的 DbContext 类中覆盖此方法以将其映射到您选择的表:

    protected override void OnModelCreating(DbModelBuilder modelBuilder) 
        modelBuilder.Entity<IdentityUser>()
            .ToTable("AspNetUsers");

【讨论】:

别忘了调用base.OnModelCreating(modelBuilder); 否则模型的其余部分将不会创建。 我在实施@Hao Kung 的解决方案后更新了我的问题,但问题仍然存在,请参阅上面我编辑的问题。谢谢。

以上是关于使用 ASP.NET Identity 时如何更改表名?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 ASP.Net MVC Identity 2 中更改密码验证?

使用asp.net 5时如何更改登录网址

Asp.net Identity 2.0 更新用户

asp.net-identity 交易问题

ASP.NET Identity 重置密码

在 ASP.NET Core 中使用基于本地存储的 JWT-Token 更改用户密码(ASP.Identity)