Как изменить имена таблиц при использовании удостоверения 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. Мне бы
  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 в «User». Мое поведение совсем другое. При первом создании он создает таблицы по мере необходимости и с указанными именами .... Может быть, просто для "эксперимента" попробуйте изменить ApplicationUser на User, а затем добавить строки base.OnModelCreating (modelBuilder); modelBuilder.Entity <IdentityUser> () .ToTable ("Users", "dbo"); modelBuilder.Entity <ApplicationUser> () .ToTable ("Users", "dbo");
Петр Стулинский

1
Обновленное решение выше ...
user2315985

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

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

Ответы:


125

Вы можете сделать это легко, изменив IdentityModel.cs, как показано ниже:

Переопределите OnModelCreating в вашем DbContext, затем добавьте следующее, это изменит таблицу 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");
        }
    }

Обратите внимание, что мне не удалось заставить это работать, если текущая таблица существует. Также обратите внимание, какие столбцы не отображаются, будут созданы столбцы по умолчанию.

Надеюсь, это поможет.


2
Чтобы эти изменения вступили в силу, вам нужно использовать миграции, чтобы перенести изменения в существующую базу данных.
Лукаш

2
Если вы сделаете это, ваши внешние ключи будут немного странными, я не думаю, что вам нужно менять имя таблицы в IdentityUser. Смотрите это ТАКОЕ сообщение
Мэтт Всего

Так же, как дополнительная проверка, как это поймали меня ранее. Убедитесь, что вызов 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?
Мариуш Джамро

Сделал небольшую правку, так как мне как-то удалось понизить этот ответ и не заметил! Также обновил его, чтобы использовать предпочтительный метод для таких ссылок[text](link)
DavidG

Я создал пустой проект MVC, запустил его 1 раз, и были созданы таблицы с именами asp. Затем я добавил это небольшое изменение, удалил все мои таблицы и папку миграции (для чего это стоило) и снова запустил мой код, но таблицы отказались переименовываться. Затем я создал совершенно новый проект, сделал это изменение перед запуском, и теперь он работает. Я что-то упускаю очень очевидное?
mathkid91

15

Вы можете попробовать переопределить этот метод в своем классе DbContext, чтобы сопоставить его с таблицей по вашему выбору:

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

7
Не забудьте позвонить, base.OnModelCreating(modelBuilder);иначе модель не будет создана.
Ферруччо

Я обновил свой вопрос после реализации решения @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), все ответы на мой комментарий верны, но вы можете просто воспользоваться этим методом, данным Александру Букуром в его блоге.

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

    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.