Làm cách nào để thay đổi tên bảng khi sử dụng ASP.NET Identity?


213

Tôi đang sử dụng phiên bản phát hành (RTM, không phải RC) của Visual Studio 2013 (được tải xuống từ MSDN 2013-10-18) và do đó là phiên bản (RTM) mới nhất của AspNet.Identity. Khi tôi tạo một dự án web mới, tôi chọn "Tài khoản người dùng cá nhân" để xác thực. Điều này tạo ra các bảng sau:

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

Khi tôi đăng ký người dùng mới (sử dụng mẫu mặc định), các bảng này (được liệt kê ở trên) được tạo và bảng AspNetUsers có một bản ghi được chèn có chứa:

  1. Tôi
  2. Tên tài khoản
  3. Mật khẩu
  4. Bảo mật
  5. Phân biệt đối xử

Ngoài ra, bằng cách thêm các thuộc tính công khai vào lớp "ApplicationUser", tôi đã thêm thành công các trường bổ sung vào bảng AspNetUsers, chẳng hạn như "FirstName", "LastName", "PhoneNumber", v.v.

Đây là câu hỏi của tôi. Có cách nào để thay đổi tên của các bảng trên (khi chúng được tạo lần đầu tiên) hay chúng sẽ luôn được đặt tên với AspNettiền tố như tôi đã liệt kê ở trên? Nếu tên bảng có thể được đặt tên khác nhau, vui lòng giải thích làm thế nào.

- CẬP NHẬT -

Tôi đã thực hiện giải pháp của @Hao Kung. Nó tạo ra một bảng mới (ví dụ tôi gọi nó là MyUsers), nhưng nó vẫn tạo bảng AspNetUsers. Mục tiêu là thay thế bảng "AspNetUsers" bằng bảng "MyUsers". Xem mã dưới đây và hình ảnh cơ sở dữ liệu của các bảng được tạo.

Tôi thực sự muốn thay thế mỗi AspNetbảng bằng tên riêng của mình ... Đối với fxample, MyRoles, MyUserClaims, MyUserLogins, MyUserRoles và MyUsers.

Làm thế nào để tôi thực hiện điều này và kết thúc chỉ với một bộ bảng?

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

Bảng cơ sở dữ liệu

- CẬP NHẬT TRẢ LỜI -

Cảm ơn cả Hao Kung và Peter Stulinski. Điều này đã giải quyết vấn đề của tôi ...

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

Bạn có chắc không? Vui lòng xóa tất cả các bảng của bạn, xóa bảng _migration của bạn và sau đó thử. Mã tôi đã đăng dưới đây rất giống với mã của bạn không tạo bảng AspNetUsers.
Piotr Stulinski

1
Sự khác biệt duy nhất giữa mã của bạn và mã của tôi là tôi đã đổi tên ApplicationUser thành "Người dùng". Cách cư xử của tôi khá khác biệt. Trong lần tạo đầu tiên, nó tạo các bảng khi cần và với tên tôi chỉ định .... Có thể chỉ vì "thử nghiệm", hãy thử thay đổi ApplicationUser thành User và sau đó thêm các dòng base.OnModelCreating (modelBuilder); modelBuilder.Entity <IdentityUser> () .ToTable ("Người dùng", "dbo"); modelBuilder.Entity <ApplicationUser> () .ToTable ("Người dùng", "dbo");
Piotr Stulinski

1
Giải pháp cập nhật ở trên ...
user2315985

6
@Daskul Xóa modelBuilder.Entity <IdentityUser> (). ToTable ("MyUsers"). Thuộc tính (p => p.Id) .HasColumnName ("UserId"); và trong trường hợp đó, cột phân biệt sẽ không được thêm vào bảng MyUsers. Xem lỗi này để biết thêm thông tin: stackoverflow.com/questions/22054168/ trộm
Sergey

1
@ user2315985 - Bạn nên cập nhật câu trả lời của mình để xóa dòng chứa modelBuilder.Entity<IdentityUser>().ToTable("MyUsers").Property(p => p.Id).HasColumnName("UserId");như được đề cập bởi @Sergey. MyUsersMặt khác, bảng mới được đặt tên có một cột phân biệt đối xử như @Daskul đã chỉ ra. Ngoài ra, MyUserClaimscấu trúc bảng của bạn sẽ sai khi @Matt Nhìn chung chỉ ra. Tôi nghĩ rằng ý tưởng để thêm nó xuất phát từ một bình luận cho @Giang trong một blog msDN , nhưng nó sai!
kimbaudi

Câu trả lời:


125

Bạn có thể thực hiện việc này một cách dễ dàng bằng cách sửa đổi IdentityModel.cs theo như dưới đây:

Ghi đè OnModelCreating trong DbContext của bạn sau đó thêm phần sau, điều này sẽ thay đổi bảng AspNetUser thành "Người dùng", bạn cũng có thể thay đổi tên trường mà cột Id mặc định sẽ trở thành User_Id.

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

hoặc đơn giản là dưới đây nếu bạn muốn giữ tất cả các tên cột tiêu chuẩn:

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

Ví dụ đầy đủ bên dưới (cái này phải có trong tệp IdentityModel.cs của bạn) tôi đã thay đổi lớp ApplicationUser của mình để được gọi là Người dùng.

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

Xin lưu ý rằng tôi đã không quản lý để làm việc này nếu bảng hiện tại tồn tại. Cũng lưu ý bất kỳ cột nào bạn không ánh xạ, các cột mặc định sẽ được tạo.

Mong rằng sẽ giúp.


2
Để có được những thay đổi này có hiệu lực, bạn cần sử dụng chuyển đổi để đẩy các thay đổi vào cơ sở dữ liệu hiện có.
Lukasz

2
Nếu bạn làm điều này, các khóa ngoại của bạn sẽ hơi kỳ lạ, tôi không nghĩ bạn bắt buộc phải thay đổi tên bảng trên IdentityUser. Xem bài đăng SO
Matt Tổng thể

Chỉ là một kiểm tra thêm vì điều này bắt tôi ra trước đây. Đảm bảo rằng lệnh gọi base.OnModelCreatinglà dòng mã đầu tiên trong phần ghi đè nếu không phần còn lại của dòng được ghi đè bởi lớp Nhận dạng cơ sở.
DavidG

@DavidG Cảm ơn bạn thực sự
SA

Giải pháp tốt. Nhưng không cần thiết phải ghi đè tên bảng cho IdentityUser. Xem giải pháp này stackoverflow.com/questions/28016684/
Mạnh

59

Dưới đây là giải pháp làm việc của tôi:

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

Xem cái này để biết thêm chi tiết


Bạn có thể làm điều đó bằng cách chỉ định các thuộc tính thay vì api trôi chảy (xấu xí) không?
Mariusz Jamro

Thực hiện một chỉnh sửa nhỏ vì bằng cách nào đó tôi đã quản lý để hạ thấp câu trả lời này và không để ý! Đồng thời cập nhật nó để sử dụng phương thức ưa thích cho các liên kết như thế này[text](link)
DavidG

Tôi đã tạo một dự án MVC trống, chạy nó 1 lần và các bảng có tên asp được tạo. Sau đó, tôi đã thêm thay đổi nhỏ này, xóa tất cả các bảng và thư mục di chuyển của mình (với giá trị của nó) và chạy lại mã của tôi, nhưng các bảng từ chối đổi tên. Sau đó tôi đã tạo ra một dự án hoàn toàn mới, thực hiện thay đổi này trước khi chạy và bây giờ nó đang hoạt động. Có phải tôi đang thiếu một cái gì đó rất rõ ràng ??
mathkid91

15

Bạn có thể thử ghi đè phương thức này trong lớp DbContext của bạn để ánh xạ nó tới một bảng bạn chọn:

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

7
Đừng quên gọi base.OnModelCreating(modelBuilder);hoặc phần còn lại của mô hình sẽ không được tạo.
Ferruccio

Tôi đã cập nhật câu hỏi của mình sau khi triển khai giải pháp của @Hao Kung nhưng vấn đề vẫn còn, vui lòng xem câu hỏi đã được chỉnh sửa của tôi ở trên. Cảm ơn.
dùng2315985

1

Bạn cũng có thể tạo các lớp cấu hình và chỉ định từng chi tiết của từng lớp Nhận dạng của mình, ví dụ:

using System.Data.Entity.ModelConfiguration;

public class ApplicationUserConfig : EntityTypeConfiguration<ApplicationUser>
{
    public UserConfig()
    {
        ToTable("Users");
        Property(u => u.LocationName).IsRequired();
    }
}

Và sau đó bao gồm các cấu hình này trong phương thức OnModelCreating ():

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

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

Điều này sẽ cung cấp cho bạn toàn quyền kiểm soát mọi khía cạnh của các lớp Danh tính.


1

Chỉ với mục đích tài liệu, đối với người đến với bài đăng này trong nhiều năm về tương lai, (như tôi XD), tất cả các câu trả lời từ nhận xét của tôi đều đúng, nhưng bạn có thể đơn giản tìm hiểu phương pháp này do Alexandru Bucur đưa ra trên blog của mình

         //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

Chúng tôi có thể thay đổi tên bảng mặc định danh tính asp.net như thế này:

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

Hơn nữa, chúng tôi có thể mở rộng từng lớp và thêm bất kỳ thuộc tính nào vào các lớp như '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
}

Để tiết kiệm thời gian, chúng ta có thể sử dụng Mẫu dự án mở rộng AspNet 2.0 để mở rộng tất cả các lớp.


0

Nhưng nó không hoạt động trong .NET CORE (MVC 6) vì chúng ta cần thay đổi liên kết thành

giống

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

Nó có thể giúp ai đó :)


cái này có hoạt động cho cả mã đầu tiên và đầu tiên cơ sở dữ liệu không?
liang

Tôi chưa thử cơ sở dữ liệu trước nhưng tôi đoán nó sẽ hoạt động nếu mô hình và cơ sở dữ liệu giống nhau.
dnxit
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.