Як я можу змінити назви таблиць при використанні ідентичності ASP.NET?


213

Я використовую версію випуску (RTM, не RC) Visual Studio 2013 (завантажена з MSDN 2013-10-18), і тому останню (RTM) версію AspNet.Identity. Коли я створюю новий веб-проект, я вибираю "Індивідуальні облікові записи користувачів" для аутентифікації. Це створює такі таблиці:

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

Коли я реєструю нового користувача (використовуючи шаблон за замовчуванням), ці таблиці (перераховані вище) створюються, і в таблицю AspNetUsers вставляється запис, який містить:

  1. Id
  2. UserName
  3. PasswordHash
  4. SecurityStamp
  5. Дискримінатор

Крім того, додавши загальнодоступні властивості до класу "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");
    }
}

Таблиці баз даних

- ОНОВЛЕННЯ ВІДПОВІДЬ -

Завдяки і Хао Кунгу, і Петру Стулінським. Це вирішило мою проблему ...

    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.
Пьотр Стулінський

1
Єдина відмінність вашого коду від моєї полягає в тому, що я перейменував ApplicationUser на "Користувач". Моя поведінка зовсім інша. Спочатку створюйте, він створює таблиці за потребою та з назвами, які я вказую .... Можливо, просто для "експериментування" спробуйте змінити ApplicationUser на користувача та додайте рядки base.OnModelCreating (modelBuilder); modelBuilder.Entity <IdentityUser> () .ToTable ("Користувачі", "dbo"); modelBuilder.Entity <ApplicationUser> () .ToTable ("Користувачі", "dbo");
Петро Стулінський

1
Оновлене рішення вище ...
користувач2315985

6
@Daskul Видалити modelBuilder.Entity <IdentityUser> () .ToTable ("MyUsers"). Властивість (p => p.Id) .HasColumnName ("UserId"); і в цьому випадку стовпчик-дискримінатор не буде доданий до таблиці MyUsers. Дивіться цю помилку для отримання додаткової інформації: stackoverflow.com/questions/22054168/…
Сергій

1
@ user2315985 - Вам слід оновити свою відповідь, щоб видалити рядок, що містить, modelBuilder.Entity<IdentityUser>().ToTable("MyUsers").Property(p => p.Id).HasColumnName("UserId");як згадував @Sergey. Інакше щойно названа MyUsersтаблиця має стовпчик-дискримінатор, як вказував @Daskul. Крім того, ваша MyUserClaimsтаблиця буде неправильною, як вказував @Matt General. Я думаю, що ідея додати, що виникла з коментаря до @Giang у блозі msdn , але її неправильна!
кімбауді

Відповіді:


125

Це можна легко зробити, змінивши IdentityModel.cs, як зазначено нижче:

Замініть OnModelCreating у вашому DbContext, а потім додайте наступне, це змінить таблицю AspNetUser на "Користувачі", ви також можете змінити імена полів, коли стовпець 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, щоб його називали користувачем.

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
Щоб ці зміни вступили в дію, вам потрібно використовувати міграції для переміщення змін до існуючої бази даних.
Лукаш

2
Якщо ви це зробите, ваші зовнішні ключі будуть трохи дивними, я не думаю, що вам потрібно змінювати ім’я таблиці на IdentityUser. Дивіться цей пост SO
Метт загалом

Так само, як додаткова перевірка, як це мене раніше спіймало. Переконайтеся, що виклик до base.OnModelCreating- це перший рядок коду в перезаписі, інакше решта рядків буде перезаписана базовим класом ідентичності.
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?
Маріуш Джамро

Зробив незначну редакцію, оскільки якось мені вдалося спростувати цю відповідь і не помітив! Також оновив його, щоб використовувати бажаний метод для таких посилань[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, але проблема не зникає, дивіться моє відредаговане питання вище. Дякую.
користувач2315985

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), всі відповіді, що відмовилися від мого коментаря, є правильними, але ви можете просто спростити цей метод, поданий Олександром Букур у своєму блозі

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

Ми можемо змінити назви таблиць за замовчуванням aspity 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 Розширюваний шаблон проекту для розширення всіх класів.


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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.