Wie kann ich die Tabellennamen bei Verwendung von ASP.NET Identity ändern?

213

Ich verwende die Release-Version (RTM, nicht RC) von Visual Studio 2013 (heruntergeladen von MSDN 2013-10-18) und daher die neueste (RTM) Version von AspNet.Identity. Wenn ich ein neues Webprojekt erstelle, wähle ich "Individuelle Benutzerkonten" zur Authentifizierung aus. Dadurch werden die folgenden Tabellen erstellt:

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

Wenn ich einen neuen Benutzer registriere (unter Verwendung der Standardvorlage), werden diese Tabellen (oben aufgeführt) erstellt und in die AspNetUsers-Tabelle wird ein Datensatz eingefügt, der Folgendes enthält:

  1. Ich würde
  2. Nutzername
  3. PasswordHash
  4. Sicherheitsstempel
  5. Diskriminator

Durch Hinzufügen öffentlicher Eigenschaften zur Klasse "ApplicationUser" habe ich der AspNetUsers-Tabelle erfolgreich zusätzliche Felder hinzugefügt, z. B. "Vorname", "Nachname", "Telefonnummer" usw.

Hier ist meine Frage. Gibt es eine Möglichkeit, die Namen der oben genannten Tabellen zu ändern (wenn sie zum ersten Mal erstellt werden), oder werden sie immer mit dem AspNetoben aufgeführten Präfix benannt ? Wenn die Tabellennamen unterschiedlich benannt werden können, erläutern Sie bitte, wie.

- UPDATE -

Ich habe die Lösung von @Hao Kung implementiert. Es wird zwar eine neue Tabelle erstellt (zum Beispiel habe ich sie MyUsers genannt), aber es wird auch weiterhin die AspNetUsers-Tabelle erstellt. Ziel ist es, die Tabelle "AspNetUsers" durch die Tabelle "MyUsers" zu ersetzen. Siehe Code unten und Datenbankabbildung der erstellten Tabellen.

Ich möchte eigentlich jede AspNetTabelle durch meinen eigenen Namen ersetzen ... Zum Beispiel MyRoles, MyUserClaims, MyUserLogins, MyUserRoles und MyUsers.

Wie schaffe ich das und erhalte nur einen Satz Tabellen?

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

Datenbanktabellen

- UPDATE ANTWORT -

Vielen Dank an Hao Kung und Peter Stulinski. Das hat mein Problem gelöst ...

    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
quelle
Bist du sicher? Bitte löschen Sie alle Ihre Tabellen, entfernen Sie Ihre _migrationstabelle und versuchen Sie es dann. Der Code, den ich unten gepostet habe und der Ihrem sehr ähnlich ist, erstellt die AspNetUsers-Tabelle nicht.
Piotr Stulinski
1
Der einzige Unterschied zwischen Ihrem und meinem Code besteht darin, dass ich ApplicationUser in "User" umbenannt habe. Mein Verhalten ist ganz anders. Beim ersten Erstellen werden die Tabellen nach Bedarf und mit den von mir angegebenen Namen erstellt. Vielleicht versuchen Sie nur zum "Experimentieren", ApplicationUser in User zu ändern, und fügen Sie dann die Zeilen base.OnModelCreating (modelBuilder) hinzu. modelBuilder.Entity <IdentityUser> () .ToTable ("Benutzer", "dbo"); modelBuilder.Entity <ApplicationUser> () .ToTable ("Users", "dbo");
Piotr Stulinski
1
Aktualisierte Lösung oben ...
user2315985
6
@Daskul Remove modelBuilder.Entity <IdentityUser> () .ToTable ("MyUsers"). Property (p => p.Id) .HasColumnName ("UserId"); In diesem Fall wird die Diskriminatorspalte nicht zur MyUsers-Tabelle hinzugefügt. Siehe diesen Fehler für weitere Informationen: stackoverflow.com/questions/22054168/…
Sergey
1
@ user2315985 - Sie sollten Ihre Antwort aktualisieren, um die modelBuilder.Entity<IdentityUser>().ToTable("MyUsers").Property(p => p.Id).HasColumnName("UserId");von @Sergey erwähnte Zeile zu entfernen . Andernfalls hat die neu benannte MyUsersTabelle eine Diskriminatorspalte, wie @Daskul hervorhob. Außerdem ist Ihre MyUserClaimsTabellenstruktur falsch, wie @Matt Overall hervorhob. Ich denke, die Idee, das hinzuzufügen, kam von einem Kommentar zu @Giang in einem MSDN-Blog , aber es ist falsch!
Kimbaudi

Antworten:

125

Sie können dies einfach tun, indem Sie IdentityModel.cs wie folgt ändern:

Überschreiben Sie OnModelCreating in Ihrem DbContext und fügen Sie Folgendes hinzu. Dadurch wird die AspNetUser-Tabelle in "Benutzer" geändert. Sie können auch die Feldnamen ändern. Die Standard-ID-Spalte wird zu User_Id.

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

oder einfach das Folgende, wenn Sie alle Standardspaltennamen behalten möchten:

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

Vollständiges Beispiel unten (dies sollte in Ihrer IdentityModel.cs-Datei sein) Ich habe meine ApplicationUser-Klasse so geändert, dass sie Benutzer heißt.

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

Bitte beachten Sie, dass ich es nicht geschafft habe, dies zum Laufen zu bringen, wenn die aktuelle Tabelle existiert. Beachten Sie auch, dass alle Spalten, die Sie nicht zuordnen, erstellt werden.

Hoffentlich hilft das.

Piotr Stulinski
quelle
2
Damit diese Änderungen wirksam werden, müssen Sie Migrationen verwenden, um die Änderungen in die vorhandene Datenbank zu übertragen.
Lukasz
2
Wenn Sie dies tun, werden Ihre Fremdschlüssel etwas seltsam sein. Ich glaube nicht, dass Sie den Tabellennamen in IdentityUser ändern müssen. Siehe diesen SO-Beitrag
Matt Overall
Nur so ein zusätzlicher Scheck, wie mich das vorher erwischt hat. Stellen Sie sicher, dass der Aufruf von base.OnModelCreatingdie erste Codezeile in der Überschreibung ist, da sonst die restlichen Zeilen von der Basisidentitätsklasse überschrieben werden.
DavidG
@ DavidG Vielen Dank in der Tat
SA
Gute Lösung. Es ist jedoch nicht erforderlich, den Tabellennamen für IdentityUser zu überschreiben. Siehe diese Lösung stackoverflow.com/questions/28016684/…
EJW
59

Unten ist meine Arbeitslösung:

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

Sehen Sie dies für weitere Einzelheiten

Frank Myat Do.
quelle
Können Sie dies tun, indem Sie Attribute anstelle der (hässlichen) fließenden API angeben?
Mariusz Jamro
Ich habe eine kleine Änderung vorgenommen, da ich es irgendwie geschafft habe, diese Antwort herunterzustimmen und es nicht bemerkt habe! Außerdem wurde es aktualisiert, um die bevorzugte Methode für Links wie diesen zu verwenden[text](link)
DavidG
Ich habe ein leeres MVC-Projekt erstellt, es einmal ausgeführt und die asp-benannten Tabellen wurden erstellt. Dann habe ich diese geringfügige Änderung hinzugefügt, alle meine Tabellen und den Migrationsordner gelöscht (was auch immer es wert ist) und meinen Code erneut ausgeführt, aber die Tabellen wollten nicht umbenannt werden. Ich habe dann ein völlig neues Projekt erstellt, diese Änderung vor dem Ausführen vorgenommen und jetzt funktioniert es. Vermisse ich etwas sehr offensichtliches?
Mathkid91
15

Sie können versuchen, diese Methode in Ihrer DbContext-Klasse zu überschreiben, um sie einer Tabelle Ihrer Wahl zuzuordnen:

    protected override void OnModelCreating(DbModelBuilder modelBuilder) {
        modelBuilder.Entity<IdentityUser>()
            .ToTable("AspNetUsers");
Hao Kung
quelle
7
Vergessen Sie nicht anzurufen, base.OnModelCreating(modelBuilder);sonst wird der Rest des Modells nicht erstellt.
Ferruccio
Ich habe meine Frage nach der Implementierung der Lösung von @Hao Kung aktualisiert, aber das Problem besteht weiterhin. Siehe meine bearbeitete Frage oben. Vielen Dank.
user2315985
1

Sie können auch Konfigurationsklassen erstellen und jedes Detail jeder Ihrer Identitätsklassen angeben, zum Beispiel:

using System.Data.Entity.ModelConfiguration;

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

Fügen Sie dann diese Konfigurationen in die OnModelCreating () -Methode ein:

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

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

Auf diese Weise haben Sie die vollständige Kontrolle über alle Aspekte der Identitätsklassen.

Manish
quelle
1

Nur zu Dokumentationszwecken, für denjenigen, der in den nächsten Jahren zu diesem Beitrag kommt (wie ich XD), sind alle Antworten, die meinen Kommentar aufgegeben haben, richtig, aber Sie können einfach mit dieser Methode von Alexandru Bucur in seinem Blog rechnen

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

Wir können die Standardtabellennamen der asp.net-Identität folgendermaßen ändern:

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

Darüber hinaus können wir jede Klasse erweitern und Klassen wie 'IdentityUser', 'IdentityRole', ... eine beliebige Eigenschaft hinzufügen.

    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
}

Um Zeit zu sparen, können wir die erweiterbare AspNet Identity 2.0-Projektvorlage verwenden , um alle Klassen zu erweitern.

Arvand
quelle
0

In .NET CORE (MVC 6) funktioniert dies jedoch nicht, da wir die Bindung ändern müssen

mögen

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

Es könnte jemandem helfen :)

dnxit
quelle
Funktioniert dies sowohl für Code-First als auch für Database-First?
Liang
Ich habe nicht zuerst versucht, eine Datenbank zu erstellen, aber ich denke, es sollte funktionieren, wenn Modell und Datenbank identisch sind.
dnxit