Renaming the Database Model of ASP.NET Core Identity

I always shake in horror when it comes to implementing my own user management in an application.

There is so much you can get wrong. And so much we need to reinvent! What about implementing...

  • Two Factor Authentication?
  • Registration?
  • Registration Confirmations?
  • Safe Password Hashing?
  • Roles and Claims?

Time is money. And time is often a very limiting factor in projects.

That's why I am using the ASP.NET Core Identity package to get a very good starting point for user management.

What's the problem?

The Database Model generated by ASP.NET Core Identity has table and column names, that nicely fit into the SQL Server Naming Conventions. But in database systems like PostgreSQL you really don't want to quote tables like myschema."AspNetUserLogins" when being used in queries.

PostgreSQL is among the databases to use SnakeCase names for entities, so a table like myschema."AspNetUserLogins" would become something along the lines of myschema.asp_net_user_logins". Plus you want the properties like "Id" written in snake case like id.

A solution for PostgreSQL

Microsoft has quite an extensive page on customizing the Identity model:

And here is how I would rename tables and columns of the identity model for Npgsql.

Plus move it into a different schema called myschema:

// ...
using Npgsql.NameTranslation;
// ...

namespace Database.Context
{
    public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
    {
        public ApplicationDbContext(DbContextOptions options)
            : base(options)
        {
        }

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

            // Move Identity to "myschema" Schema:
            modelBuilder.Entity<ApplicationUser>().ToTable("application_user", "myschema");
            modelBuilder.Entity<IdentityRole>().ToTable("role", "myschema");
            modelBuilder.Entity<IdentityUserToken<string>>().ToTable("user_token", "myschema");
            modelBuilder.Entity<IdentityUserRole<string>>().ToTable("user_role", "myschema");
            modelBuilder.Entity<IdentityRoleClaim<string>>().ToTable("role_claim", "myschema");
            modelBuilder.Entity<IdentityUserClaim<string>>().ToTable("user_claim", "myschema");
            modelBuilder.Entity<IdentityUserLogin<string>>().ToTable("user_login", "myschema");

            // Apply Snake Case Names for Properties:
            ApplySnakeCaseNames(modelBuilder);
        }

        private void ApplySnakeCaseNames(ModelBuilder modelBuilder)
        {
            var mapper = new NpgsqlSnakeCaseNameTranslator();

            foreach (var entity in modelBuilder.Model.GetEntityTypes())
            {
                foreach (var property in entity.GetProperties())
                {
                    var npgsqlColumnName = mapper.TranslateMemberName(property.GetColumnName());

                    property.SetColumnName(npgsqlColumnName);
                }
            }
        }

        // ... More Code
    }
}

Conclusion

There are some entities missing, such as Foreign Key and Constraint names.

If you have a more complete solution to share, please let me know and the solution above could be extended.

How to contribute

One of the easiest ways to contribute is to participate in discussions. You can also contribute by submitting pull requests.

General feedback and discussions?

Do you have questions or feedback on this article? Please create an issue on the GitHub issue tracker.

Something is wrong or missing?

There may be something wrong or missing in this article. If you want to help fixing it, then please make a Pull Request to this file on GitHub.