ฉันจะเปลี่ยนชื่อตารางเมื่อใช้ ASP.NET Identity ได้อย่างไร


213

ฉันกำลังใช้รุ่นที่วางจำหน่าย (RTM ไม่ใช่ RC) ของ Visual Studio 2013 (ดาวน์โหลดจาก MSDN 2013-10-18) ดังนั้น AspNet.Identity รุ่นล่าสุด (RTM) เมื่อฉันสร้างโครงการเว็บใหม่ฉันเลือก "บัญชีผู้ใช้ส่วนบุคคล" สำหรับการตรวจสอบ สิ่งนี้สร้างตารางต่อไปนี้:

  1. AspNetRoles
  2. AspNetUserClaims
  3. AspNetUserLogins
  4. AspNetUserRoles
  5. AspNetUsers

เมื่อฉันลงทะเบียนผู้ใช้ใหม่ (โดยใช้เทมเพลตเริ่มต้น) ตารางเหล่านี้ (รายการด้านบน) จะถูกสร้างขึ้นและตาราง AspNetUsers จะมีการบันทึกแทรกซึ่งประกอบด้วย:

  1. Id
  2. ชื่อผู้ใช้
  3. PasswordHash
  4. SecurityStamp
  5. discriminator

นอกจากนี้โดยการเพิ่มคุณสมบัติสาธารณะในคลาส "ApplicationUser" ฉันได้เพิ่มฟิลด์เพิ่มเติมลงในตาราง AspNetUsers เช่น "FirstName", "LastName", "PhoneNumber" เป็นต้น

นี่คือคำถามของฉัน มีวิธีการเปลี่ยนชื่อของตารางข้างต้น (เมื่อพวกเขาถูกสร้างขึ้นครั้งแรก) หรือพวกเขาจะถูกตั้งชื่อด้วยAspNetคำนำหน้าตามที่ฉันระบุไว้ข้างต้นหรือไม่ หากชื่อตารางแตกต่างกันโปรดอธิบายวิธีการ

- อัปเดต -

ฉันใช้งานโซลูชันของ @Hao Kung มันสร้างตารางใหม่ (เช่นฉันเรียกว่า MyUsers) แต่ก็ยังสร้างตาราง AspNetUsers เป้าหมายคือการแทนที่ตาราง "AspNetUsers" ด้วยตาราง "MyUsers" ดูรหัสด้านล่างและภาพฐานข้อมูลของตารางที่สร้าง

ฉันต้องการแทนที่แต่ละ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
Piotr Stulinski

1
ข้อแตกต่างระหว่างรหัสของคุณกับของฉันคือฉันเปลี่ยนชื่อ ApplicationUser เป็น "ผู้ใช้" พฤติกรรมของฉันแตกต่างกันมาก ในการสร้างครั้งแรกมันสร้างตารางตามที่ต้องการและด้วยชื่อที่ฉันระบุ .... อาจจะเป็นเพียงแค่สำหรับ "ทดลอง" ลองเปลี่ยน ApplicationUser เป็นผู้ใช้แล้วเพิ่มบรรทัด baseOnModelCreating (modelBuilder); modelBuilder.Entity <IdentityUser> () .ToTable ("ผู้ใช้", "dbo"); modelBuilder.Entity <ApplicationUser> () .ToTable ("Users", "dbo");
Piotr Stulinski

1
อัปเดตโซลูชันด้านบน ...
user2315985

6
@Daskul ลบ modelBuilder.Entity <IdentityUser> () .ToTable ("MyUsers"). คุณสมบัติ (p => p.Id) .HasColumnName ("UserId"); และในกรณีนั้นคอลัมน์ discriminator จะไม่ถูกเพิ่มลงในตาราง MyUsers ดูข้อผิดพลาดนี้สำหรับข้อมูลเพิ่มเติม: stackoverflow.com/questions/22054168/…
Sergey

1
@ user2315985 - คุณควรอัปเดตคำตอบเพื่อลบบรรทัดที่มีmodelBuilder.Entity<IdentityUser>().ToTable("MyUsers").Property(p => p.Id).HasColumnName("UserId");@Sergey ดังกล่าว มิฉะนั้นMyUsersตารางที่เพิ่งตั้งชื่อใหม่จะมีคอลัมน์ตัวเลือกตามที่ @Daskul ชี้ให้เห็น นอกจากนี้MyUserClaimsโครงสร้างตารางของคุณจะผิดเพราะ @Matt Total ชี้ให้เห็น ฉันคิดว่าความคิดที่จะเพิ่มสิ่งนั้นมาจากความคิดเห็นที่ @Giang ในบล็อก msdn แต่มันผิด
kimbaudi

คำตอบ:


125

คุณสามารถทำได้อย่างง่ายดายโดยแก้ไข IdentityModel.cs ดังต่อไปนี้:

แทนที่ OnModelCreating ใน DbContext ของคุณจากนั้นเพิ่มสิ่งต่อไปนี้ซึ่งจะเปลี่ยนตาราง AspNetUser เป็น "ผู้ใช้" คุณยังสามารถเปลี่ยนชื่อฟิลด์ที่คอลัมน์รหัสเริ่มต้นจะกลายเป็น User_Id

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

หรือเพียงแค่ด้านล่างหากคุณต้องการเก็บชื่อคอลัมน์มาตรฐานทั้งหมด:

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

ตัวอย่างเต็มด้านล่าง (ซึ่งควรอยู่ในไฟล์ IdentityModel.cs ของคุณ) ฉันเปลี่ยนคลาส ApplicationUser ของฉันให้เป็นชื่อผู้ใช้

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

โปรดทราบฉันยังไม่ได้รับการจัดการเพื่อให้ทำงานได้หากตารางปัจจุบันอยู่ โปรดทราบด้วยว่าคอลัมน์ใดที่คุณไม่ได้จับคู่กับค่าเริ่มต้นจะถูกสร้างขึ้น

หวังว่าจะช่วย


2
เพื่อให้การเปลี่ยนแปลงเหล่านี้มีผลคุณต้องใช้การย้ายข้อมูลเพื่อผลักดันการเปลี่ยนแปลงไปยังฐานข้อมูลที่มีอยู่
Lukasz

2
หากคุณทำสิ่งนี้กุญแจต่างประเทศของคุณจะแปลกไปหน่อยฉันไม่คิดว่าคุณจะต้องเปลี่ยนชื่อตารางใน IdentityUser ดูโพสต์ SO
แมตต์โดยรวม

เป็นการตรวจสอบพิเศษอย่างนี้ทำให้ฉันออกไปก่อนหน้านี้ ตรวจสอบให้แน่ใจว่าการเรียกbase.OnModelCreatingเป็นบรรทัดแรกของรหัสในการแทนที่มิฉะนั้นบรรทัดที่เหลือจะถูกเขียนทับโดยคลาส Identity พื้นฐาน
DavidG

@DavidG ขอบคุณจริงๆ
SA

ทางออกที่ดี แต่ไม่จำเป็นต้องเขียนทับชื่อตารางสำหรับ IdentityUser ดูโซลูชันนี้stackoverflow.com/questions/28016684/…
EJW

59

ด้านล่างเป็นโซลูชันการทำงานของฉัน:

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();
    }
}

ดูนี้สำหรับรายละเอียดเพิ่มเติม


คุณสามารถทำสิ่งนั้นได้โดยการระบุคุณสมบัติแทนที่จะเป็น API ที่คล่องแคล่ว (น่าเกลียด)?
Mariusz Jamro

แก้ไขเล็กน้อยตามที่ฉันจัดการเพื่อลงคะแนนคำตอบนี้และไม่ได้แจ้งให้ทราบ! อัปเดตด้วยเพื่อใช้วิธีที่ต้องการสำหรับลิงก์เช่นนี้[text](link)
DavidG

ฉันสร้างโครงการ MVC เปล่าวิ่ง 1 ครั้งและสร้างตารางชื่อ asp จากนั้นฉันก็เพิ่มการเปลี่ยนแปลงเล็กน้อยลบตารางและโฟลเดอร์การย้ายข้อมูลทั้งหมด (สำหรับมูลค่า) และเรียกใช้รหัสของฉันอีกครั้ง แต่ตารางปฏิเสธที่จะเปลี่ยนชื่อ จากนั้นฉันสร้างโครงการใหม่ทั้งหมดทำการเปลี่ยนแปลงก่อนที่จะทำงานและตอนนี้มันทำงานได้ ฉันขาดอะไรที่ชัดเจนมากไป ??
mathkid91

15

คุณสามารถลองแทนที่เมธอดนี้ในคลาส DbContext ของคุณเพื่อแม็พกับตารางที่คุณเลือก:

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

7
อย่าลืมโทรbase.OnModelCreating(modelBuilder);หรือรุ่นที่เหลือจะไม่ถูกสร้างขึ้น
Ferruccio

ฉันอัปเดตคำถามหลังจากใช้งานโซลูชันของ @Hao Kung แล้ว แต่ปัญหายังคงมีอยู่โปรดดูคำถามที่แก้ไขแล้วของฉันด้านบน ขอบคุณ
user2315985

1

คุณยังสามารถสร้างคลาสการกำหนดค่าและระบุรายละเอียดทุกอย่างของคลาส Identity ของคุณแต่ละตัวอย่างเช่น:

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());
        ...
    }

สิ่งนี้จะช่วยให้คุณควบคุมทุกแง่มุมของคลาส Identity ได้อย่างสมบูรณ์


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

0

เราสามารถเปลี่ยนชื่อตารางเริ่มต้น 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เพื่อขยายคลาสทั้งหมด


0

แต่มันไม่ทำงานใน. 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");
    });
}

มันอาจช่วยใครซักคน :)


สิ่งนี้ใช้ได้กับทั้งรหัสแรกและฐานข้อมูลก่อนหรือไม่
เหลียง

ฉันไม่ได้ลองใช้ฐานข้อมูลก่อน แต่ฉันคิดว่ามันน่าจะใช้ได้ถ้ารุ่นและฐานข้อมูลเหมือนกัน
dnxit
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.