ASP.NET Core Identity primary key data type


.net coreAre you working on an application that is using ASP.NET Core Identity for user storage? Is the primary key datatype not what you expected? When I first added it I found that my user id was a guid. This was a big problem for me due to the fact that I was in the process of adding this to an existing system which had longs as the primary key datatype for a user. I began to consider what kind of a change it was going to require of me to update the application to support Guid primary key type. Its actually created in the database as an nvarchr(450).

I was happy to discover that it is possible to change the primary key datatype.
[wp_ad_camp_3]

Models

The first thing we need to do is create our model.


using Microsoft.AspNetCore.Identity;

namespace TestIdentity.ChangePrimaryKeyDataType.Models
{
    public class ApplicationUser : IdentityUser
    {
    }

    public class ApplicationRole : IdentityRole
    {
    }
}

Data

Then we define the ApplicationDbContext


using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
using TestIdentity.ChangePrimaryKeyDataType.Models;

namespace TestIdentity.ChangePrimaryKeyDataType.Data
{
    public class ApplicationDbContext : IdentityDbContext
    {
        public ApplicationDbContext(DbContextOptions options)
            : base(options)
        {
        }
    }
}

Startup

Then we set things up in the startup.cs


 public void ConfigureServices(IServiceCollection services)
        {

            services.AddDbContext(options =>
                options.UseSqlServer(Configuration.GetConnectionString("Default")));

            services.AddIdentity()
                .AddEntityFrameworkStores()
                .AddDefaultTokenProviders();

            // Add application services.
            services.AddTransient();
            services.AddMvc();
        }

Migrations

Now when I Genreate my migration fine I get something like this
[wp_ad_camp_5]


// 
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using System;
using TestIdentity.ChangePrimaryKeyDataType.Data;

namespace TestIdentity.ChangePrimaryKeyDataType.Migrations
{
    [DbContext(typeof(ApplicationDbContext))]
    [Migration("20171208115331_InitUsers")]
    partial class InitUsers
    {
        protected override void BuildTargetModel(ModelBuilder modelBuilder)
        {
#pragma warning disable 612, 618
            modelBuilder
                .HasAnnotation("ProductVersion", "2.0.1-rtm-125")
                .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);

            modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b =>
                {
                    b.Property("Id")
                        .ValueGeneratedOnAdd();

                    b.Property("ClaimType");

                    b.Property("ClaimValue");

                    b.Property("RoleId");

                    b.HasKey("Id");

                    b.HasIndex("RoleId");

                    b.ToTable("AspNetRoleClaims");
                });

            modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b =>
                {
                    b.Property("Id")
                        .ValueGeneratedOnAdd();

                    b.Property("ClaimType");

                    b.Property("ClaimValue");

                    b.Property("UserId");

                    b.HasKey("Id");

                    b.HasIndex("UserId");

                    b.ToTable("AspNetUserClaims");
                });

            modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b =>
                {
                    b.Property("LoginProvider");

                    b.Property("ProviderKey");

                    b.Property("ProviderDisplayName");

                    b.Property("UserId");

                    b.HasKey("LoginProvider", "ProviderKey");

                    b.HasIndex("UserId");

                    b.ToTable("AspNetUserLogins");
                });

            modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b =>
                {
                    b.Property("UserId");

                    b.Property("RoleId");

                    b.HasKey("UserId", "RoleId");

                    b.HasIndex("RoleId");

                    b.ToTable("AspNetUserRoles");
                });

            modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b =>
                {
                    b.Property("UserId");

                    b.Property("LoginProvider");

                    b.Property("Name");

                    b.Property("Value");

                    b.HasKey("UserId", "LoginProvider", "Name");

                    b.ToTable("AspNetUserTokens");
                });

            modelBuilder.Entity("TestIdentity.ChangePrimaryKeyDataType.Models.ApplicationRole", b =>
                {
                    b.Property("Id")
                        .ValueGeneratedOnAdd();

                    b.Property("ConcurrencyStamp")
                        .IsConcurrencyToken();

                    b.Property("Name")
                        .HasMaxLength(256);

                    b.Property("NormalizedName")
                        .HasMaxLength(256);

                    b.HasKey("Id");

                    b.HasIndex("NormalizedName")
                        .IsUnique()
                        .HasName("RoleNameIndex")
                        .HasFilter("[NormalizedName] IS NOT NULL");

                    b.ToTable("AspNetRoles");
                });

            modelBuilder.Entity("TestIdentity.ChangePrimaryKeyDataType.Models.ApplicationUser", b =>
                {
                    b.Property("Id")
                        .ValueGeneratedOnAdd();

                    b.Property("AccessFailedCount");

                    b.Property("ConcurrencyStamp")
                        .IsConcurrencyToken();

                    b.Property("Email")
                        .HasMaxLength(256);

                    b.Property("EmailConfirmed");

                    b.Property("LockoutEnabled");

                    b.Property("LockoutEnd");

                    b.Property("NormalizedEmail")
                        .HasMaxLength(256);

                    b.Property("NormalizedUserName")
                        .HasMaxLength(256);

                    b.Property("PasswordHash");

                    b.Property("PhoneNumber");

                    b.Property("PhoneNumberConfirmed");

                    b.Property("SecurityStamp");

                    b.Property("TwoFactorEnabled");

                    b.Property("UserName")
                        .HasMaxLength(256);

                    b.HasKey("Id");

                    b.HasIndex("NormalizedEmail")
                        .HasName("EmailIndex");

                    b.HasIndex("NormalizedUserName")
                        .IsUnique()
                        .HasName("UserNameIndex")
                        .HasFilter("[NormalizedUserName] IS NOT NULL");

                    b.ToTable("AspNetUsers");
                });

            modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b =>
                {
                    b.HasOne("TestIdentity.ChangePrimaryKeyDataType.Models.ApplicationRole")
                        .WithMany()
                        .HasForeignKey("RoleId")
                        .OnDelete(DeleteBehavior.Cascade);
                });

            modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b =>
                {
                    b.HasOne("TestIdentity.ChangePrimaryKeyDataType.Models.ApplicationUser")
                        .WithMany()
                        .HasForeignKey("UserId")
                        .OnDelete(DeleteBehavior.Cascade);
                });

            modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b =>
                {
                    b.HasOne("TestIdentity.ChangePrimaryKeyDataType.Models.ApplicationUser")
                        .WithMany()
                        .HasForeignKey("UserId")
                        .OnDelete(DeleteBehavior.Cascade);
                });

            modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b =>
                {
                    b.HasOne("TestIdentity.ChangePrimaryKeyDataType.Models.ApplicationRole")
                        .WithMany()
                        .HasForeignKey("RoleId")
                        .OnDelete(DeleteBehavior.Cascade);

                    b.HasOne("TestIdentity.ChangePrimaryKeyDataType.Models.ApplicationUser")
                        .WithMany()
                        .HasForeignKey("UserId")
                        .OnDelete(DeleteBehavior.Cascade);
                });

            modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b =>
                {
                    b.HasOne("TestIdentity.ChangePrimaryKeyDataType.Models.ApplicationUser")
                        .WithMany()
                        .HasForeignKey("UserId")
                        .OnDelete(DeleteBehavior.Cascade);
                });
#pragma warning restore 612, 618
        }
    }
}

Conclusion

It is possible to change the default primary key type of the asp.net identity tables. Full sample project can be found on GitHub


About Linda Lawton

My name is Linda Lawton I have more than 20 years experience working as an application developer and a database expert. I have also been working with Google APIs since 2012 and I have been contributing to the Google .Net client library since 2013. In 2013 I became a a Google Developer Experts for Google Analytics.

Leave a comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.