Как изменить имена таблиц при использовании удостоверения 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");
    }
user2315985
источник
Ты уверен? Удалите все таблицы, удалите таблицу _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.

Manish
источник
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));
            }
        }
sgrysoft
источник
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
источник
это работает и для кода сначала и для базы данных сначала?
Лян
Сначала я не пытался использовать базу данных, но думаю, она должна работать, если модель и база данных совпадают.
dnxit