How to make EF-Core use a Guid instead of String for its ID/Primary key

devfric picture devfric · May 11, 2016 · Viewed 21k times · Source

When I look at the ASP.NET 3 Identity it uses a string and not a Guid for the unique primary key.

In my Entity Framework code first Users' ApplicationUser class I inherit the Identity class

public class ApplicationUser : IdentityUser
{
}

which results in when I create my Entity Framework migrations a table aspnetusers getting created with a key type ofnvarchar(450) instead of uniqueidentifier

When I compare this to ASP.NET Identity 2 ENtity Framework project it created an ID field of uniqueidentifier and not nvarchar(450)

I would imagine for database performance primary keys and foreign keys of uniqueidentifier would be better than nvarchar(450)

Is there a way to use for the unique key Guid instead of string and uniqueidentifier instead of nvarchar(450) with ASP.NET Identity 3?

There is a previous question how to convert a String to a Guid but I want the database table Id to be a Guid.

I found another question as well for a previous BETA when the length was nvarchar(128). The reason given is that not all databases support Guids and it was changed for flexibility.

Is there must be an easy way to change from string to Guid without rewriting the whole identity 3?

nvarchar(450) is really overkill and gives all kinds of warnings when creating SQL Server database constraints. Database admins will definitively not like these warnings.

Answer

tmg picture tmg · May 11, 2016

You need custom ApplicationUser inherit from IdentityUser<TKey> and custom Role inherit from IdentityRole<TKey>

public class ApplicationUser : IdentityUser<Guid> { }    
public class Role : IdentityRole<Guid> { }

Custom context class inherit from IdentityDbContext<ApplicationUser, Role, TKey> and use fluent api for auto generate guid keys.

public class ApplicationDbContext : IdentityDbContext<ApplicationUser, Role, Guid>
{
    protected override void OnModelCreating(ModelBuilder builder)
    {
        base.OnModelCreating(builder);

        builder.Entity<ApplicationUser>(b =>
        {
            b.Property(u => u.Id).HasDefaultValueSql("newsequentialid()");
        });

        builder.Entity<Role>(b =>
        {
            b.Property(u => u.Id).HasDefaultValueSql("newsequentialid()");
        });
    }
}

then in Startup add Identity service to container like this

services.AddIdentity<ApplicationUser, Role>()
        .AddEntityFrameworkStores<ApplicationDbContext, Guid>()
        .AddDefaultTokenProviders()
        .AddUserStore<UserStore<ApplicationUser, Role, ApplicationDbContext, Guid>> ()
        .AddRoleStore<RoleStore<Role, ApplicationDbContext, Guid>>();

If you have not created the database, clear the migrations folder and run ef commands