Come posso cambiare i nomi delle tabelle quando utilizzo ASP.NET Identity?


213

Sto usando la versione di rilascio (RTM, non RC) di Visual Studio 2013 (scaricata da MSDN 2013-10-18) e quindi l'ultima versione (RTM) di AspNet.Identity. Quando creo un nuovo progetto Web, seleziono "Account utente individuali" per l'autenticazione. Questo crea le seguenti tabelle:

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

Quando registro un nuovo utente (usando il modello predefinito), queste tabelle (elencate sopra) vengono create e la tabella AspNetUsers ha un record inserito che contiene:

  1. Id
  2. Nome utente
  3. PasswordHash
  4. SecurityStamp
  5. Discriminatore

Inoltre, aggiungendo proprietà pubbliche alla classe "ApplicationUser" ho aggiunto correttamente campi aggiuntivi alla tabella AspNetUsers, come "FirstName", "LastName", "PhoneNumber", ecc.

Ecco la mia domanda C'è un modo per cambiare i nomi delle tabelle sopra (quando vengono create per la prima volta) o saranno sempre nominati con il AspNetprefisso come ho elencato sopra? Se i nomi delle tabelle possono essere nominati in modo diverso, spiega come.

-- AGGIORNARE --

Ho implementato la soluzione di @Hao Kung. Crea una nuova tabella (ad esempio, l'ho chiamata MyUsers), ma crea anche la tabella AspNetUsers. L'obiettivo è sostituire la tabella "AspNetUsers" con la tabella "MyUsers". Vedere il codice seguente e l'immagine del database delle tabelle create.

In realtà vorrei sostituire ogni AspNettabella con il mio nome ... Per fxample, MyRoles, MyUserClaims, MyUserLogins, MyUserRoles e MyUsers.

Come posso ottenere questo risultato e finire con un solo set di tabelle?

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

Tabelle database

- AGGIORNA RISPOSTA -

Grazie sia a Hao Kung che a Peter Stulinski. Questo ha risolto il mio problema ...

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

Sei sicuro? Elimina tutte le tue tabelle, rimuovi la tua _migration table e poi prova. Il codice che ho pubblicato di seguito che è molto simile al tuo non crea la tabella AspNetUsers.
Piotr Stulinski,

1
L'unica differenza tra il mio codice e il mio è che ho rinominato ApplicationUser in "Utente". Il mio comportamento è abbastanza diverso. Alla prima creazione crea le tabelle secondo necessità e con i nomi che specifico .... Forse solo per amor di "sperimentazione" prova a cambiare ApplicationUser in User e quindi aggiungi le righe base.OnModelCreating (modelBuilder); modelBuilder.Entity <IdentityUser> () .ToTable ("Users", "dbo"); modelBuilder.Entity <ApplicationUser> () .ToTable ("Users", "dbo");
Piotr Stulinski,

1
Soluzione aggiornata sopra ...
user2315985

6
@Daskul Rimuovi modelBuilder.Entity <IdentityUser> () .ToTable ("MyUsers"). Proprietà (p => p.Id) .HasColumnName ("UserId"); e in tal caso la colonna discriminatore non verrà aggiunta alla tabella MyUsers. Vedere questo errore per ulteriori informazioni: stackoverflow.com/questions/22054168/…
Sergey

1
@ user2315985 - È necessario aggiornare la risposta per rimuovere la riga contenente modelBuilder.Entity<IdentityUser>().ToTable("MyUsers").Property(p => p.Id).HasColumnName("UserId");come indicato da @Sergey. Altrimenti, la MyUserstabella appena nominata ha una colonna discriminatore come ha sottolineato @Daskul. Inoltre, la MyUserClaimsstruttura della tabella sarà errata, come sottolineato da @Matt Overall. Penso che l'idea di aggiungere sia nata da un commento a @Giang in un blog msdn , ma è sbagliata!
Kimbaudi,

Risposte:


125

Puoi farlo facilmente modificando IdentityModel.cs come indicato di seguito:

Sostituisci OnModelCreating nel tuo DbContext quindi aggiungi quanto segue, questo cambierà la tabella AspNetUser in "Utenti", puoi anche cambiare i nomi dei campi la colonna Id predefinita diventerà User_Id.

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

o semplicemente il seguente se si desidera mantenere tutti i nomi di colonna standard:

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

Esempio completo di seguito (questo dovrebbe essere nel tuo file IdentityModel.cs) Ho cambiato la mia classe ApplicationUser per essere chiamato Utente.

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

Si prega di notare che non sono riuscito a farlo funzionare se esiste la tabella corrente. Si noti inoltre che verranno create tutte le colonne che non si mappano quelle predefinite.

Spero che aiuti.


2
Per rendere effettive queste modifiche è necessario utilizzare le migrazioni per inviare le modifiche al database esistente.
Lukasz,

2
Se lo fai, le tue chiavi esterne saranno un po 'strane, non credo che ti venga richiesto di cambiare il nome della tabella su IdentityUser. Vedi questo messaggio SO
Matt Totale

Proprio come un controllo extra come questo mi ha sorpreso in precedenza. Assicurarsi che la chiamata a base.OnModelCreatingsia la prima riga di codice nell'override, altrimenti le altre righe vengono sovrascritte dalla classe Identity di base.
DavidG

@DavidG Grazie davvero
SA

Buona soluzione Ma non è necessario sovrascrivere il nome della tabella per IdentityUser. Vedi questa soluzione stackoverflow.com/questions/28016684/…
EJW

59

Di seguito è la mia soluzione di lavoro:

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

Vedi questo per maggiori dettagli


Puoi farlo specificando gli attributi anziché l'API (brutta) fluente?
Mariusz Jamro,

Ho apportato una modifica minore poiché in qualche modo sono riuscito a sottovalutare questa risposta e non ho notato! Anche aggiornato per utilizzare il metodo preferito per collegamenti come questo[text](link)
DavidG

Ho creato un progetto MVC vuoto, l'ho eseguito 1 volta e sono state create le tabelle con nome asp. Quindi ho aggiunto questa modifica minore, ho eliminato tutte le mie tabelle e la cartella di migrazione (per quello che vale) e ho eseguito nuovamente il mio codice, ma le tabelle hanno rifiutato di essere rinominate. Ho quindi creato un progetto completamente nuovo, ho apportato questa modifica prima di eseguirlo e ora funziona. Mi sto perdendo qualcosa di molto ovvio ??
mathkid91,

15

Puoi provare a sovrascrivere questo metodo nella tua classe DbContext per mapparlo su una tabella di tua scelta:

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

7
Non dimenticare di chiamare base.OnModelCreating(modelBuilder);o il resto del modello non verrà creato.
Ferruccio,

Ho aggiornato la mia domanda dopo aver implementato la soluzione di @Hao Kung ma il problema persiste, per favore vedi la mia domanda modificata sopra. Grazie.
user2315985

1

Puoi anche creare classi di configurazione e specificare ogni dettaglio di ciascuna delle tue classi Identity, ad esempio:

using System.Data.Entity.ModelConfiguration;

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

E quindi includere queste configurazioni nel metodo OnModelCreating ():

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

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

Questo ti darà il controllo completo su ogni aspetto delle classi di identità.


1

Solo a scopo di documentazione, per chi arriva a questo post negli anni futuri sul futuro, (come me XD), tutte le risposte fornite al mio commento sono giuste, ma puoi semplicemente semplificare con questo metodo dato da Alexandru Bucur sul suo blog

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

Possiamo modificare i nomi delle tabelle predefinite di identità asp.net in questo modo:

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

Inoltre possiamo estendere ogni classe e aggiungere qualsiasi proprietà a classi come '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
}

Per risparmiare tempo, possiamo utilizzare il modello di progetto estensibile AspNet Identity 2.0 per estendere tutte le classi.


0

Ma non funziona in .NET CORE (MVC 6) per cui dobbiamo cambiare l'associazione

piace

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

Potrebbe aiutare qualcuno :)


funziona sia per il codice che per il database?
liang,

Non ho provato prima per il database ma suppongo che dovrebbe funzionare se il modello e il database sono uguali.
dnxit
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.