45

I've used ASP.net membership for years and am just starting to try out ASP.net Identity. They just released version 2.0 and which is supposed to support int primary keys. I've defined my custom identity classes as follows in order to get integer primary key support:

public class User : IdentityUser<int, UserLogin, UserRole, UserClaim>
{  
}

public class UserLogin : IdentityUserLogin<int>
{
}

public class Role : IdentityRole<int, UserRole>
{
    public string Description { get; set; }  // Custom description field on roles
}

public class UserRole : IdentityUserRole<int>
{
}

public class UserClaim : IdentityUserClaim<int>
{
}

public class MyDbContext : IdentityDbContext<User, Role, int, UserLogin, UserRole, UserClaim>
{
    public MyDbContext() : this("MyDB") { }

    public MyDbContext(string connStringName) : base(connStringName)
    {
        this.Configuration.LazyLoadingEnabled = false;
        this.Configuration.ProxyCreationEnabled = false;
    }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {

        modelBuilder.Entity<User>().ToTable("Users");
        modelBuilder.Entity<Role>().ToTable("Roles");
        modelBuilder.Entity<UserRole>().ToTable("UserRoles");
        modelBuilder.Entity<UserLogin>().ToTable("UserLogins");
        modelBuilder.Entity<UserClaim>().ToTable("UserClaims");

        base.OnModelCreating(modelBuilder);
    }
}

When I create a database migration, it properly creates an integer Id column for each of the identity tables, however, it is ignoring my custom table names specified in the OnModelCreating method. Instead I get table names like dbo.AspNetUsers and dbo.AspNetRoles.

I've also tried adding the [Table("TableName")] to my custom identity classes and it has no effect.

In looking at examples for ASP.net Identity 1.0, it looked like they repeated each of the modelBuilder.Entry<Type>().ToTable("TableName") lines using the base Identity classes:

modelBuilder.Entity<User>().ToTable("Users");
modelBuilder.Entity<IdentityUser<int, IdentityUserLogin<int>, IdentityUserRole<int>, IdentityUserClaim<int>>>().ToTable("Users");

modelBuilder.Entity<Role>().ToTable("Roles");
modelBuilder.Entity<IdentityRole<int, UserRole>>().ToTable("Roles");

modelBuilder.Entity<UserRole>().ToTable("UserRoles");
modelBuilder.Entity<IdentityUserRole<int>>().ToTable("UserRoles");

modelBuilder.Entity<UserLogin>().ToTable("UserLogins");
modelBuilder.Entity<IdentityUserLogin<int>>().ToTable("UserLogins");

modelBuilder.Entity<UserClaim>().ToTable("UserClaims");
modelBuilder.Entity<IdentityUserClaim<int>>().ToTable("UserClaims");

However, I tried several variations and my migrations would not generate. I kept receiving errors similar to The type Microsoft.AspNet.Identity.EntityFramework.IdentityUser'4[System.Int32,Microsoft.AspNet.Identity.EntityFramework.IdentityUserLogin'1[System.Int32],Microsoft.AspNet.Identity.EntityFramework.IdentityUserRole'1[System.Int32],Microsoft.AspNet.Identity.EntityFramework.IdentityUserClaim'1[System.Int32]]' was not mapped. Check that the type has not been explicitly excluded by using the Ignore method or NotMappedAttribute data annotation. Verify that the type was defined as a class, is not primitive or generic, and does not inherit from EntityObject.

How can I generate custom table names with integer primary keys in ASP.net Identity 2.0?

Sam
  • 9,933
  • 12
  • 68
  • 104
  • if you happen to land here looking for identity 3.0, [check out this q/a](http://stackoverflow.com/questions/34523066/how-can-i-change-the-table-names-used-by-asp-net-identity-3-vnext). +1s all around –  Aug 13 '16 at 06:03

2 Answers2

78

Grrr...... So after wasting a couple hours on this, I copied my rules and pasted them below the base.OnModelCreating(modelBuilder); line and everything worked properly. I didn't realize that the base method needed to be called first :(

Everything is working properly now using the following configuration:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    base.OnModelCreating(modelBuilder); // This needs to go before the other rules!

    modelBuilder.Entity<User>().ToTable("Users");
    modelBuilder.Entity<Role>().ToTable("Roles");
    modelBuilder.Entity<UserRole>().ToTable("UserRoles");
    modelBuilder.Entity<UserLogin>().ToTable("UserLogins");
    modelBuilder.Entity<UserClaim>().ToTable("UserClaims");
}
Sam
  • 9,933
  • 12
  • 68
  • 104
  • Point of interest - base.OnModelCreating(modelBuilder); Worked for me as well.. :) – sandeep talabathula Jul 16 '14 at 19:23
  • 1
    lifesaver of a post, needing to call base imp first was not intuative at all. If using Identity 2.0, the model types are IdentityRole, IdentityUser, IdentityUseRole, etc... but the same principal applies. – Stephen M. Redd Oct 05 '14 at 03:59
  • Thank you so much! How did you find out base.OnModelCreating had to call first? – Jon Koivula Jul 23 '15 at 03:46
  • 1
    Hi Sam corrects me if I am wrong. Just wondering how your code was worked without defines the keys on tables. – PEO Jul 29 '15 at 22:59
  • My entities inherited from the Identity classes which already have keys defined. All the code above does is modify the configuration to use different table names – Sam Jul 30 '15 at 03:43
  • Note that if you have a derived class (custom role) from IdentityRole, for example, you must indicate that you use the same table for both entities: base class role, and the derived role.`modelBuilder.Entity().ToTable("UserRoles");` and `modelBuilder.Entity().ToTable("UserRoles");` – MSD561 Jan 31 '19 at 18:56
8

In the IdentityModel.cs file, I added the following code to the ApplicationDbContext class

Notice the Model names are different that that names listed in the accepted answer

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

        modelBuilder.Entity<ApplicationUser>().ToTable("SystemUsers");
        modelBuilder.Entity<IdentityRole>().ToTable("SystemRoles");
        modelBuilder.Entity<IdentityUserRole>().ToTable("SystemUserRoles");
        modelBuilder.Entity<IdentityUserLogin>().ToTable("SystemUserLogins");
        modelBuilder.Entity<IdentityUserClaim>().ToTable("SystemUserClaims");
    }
Junior
  • 11,602
  • 27
  • 106
  • 212
  • is it possible to change this permanent, event changing the following code it should remain as well – SAR Jan 04 '17 at 10:43