The entity type 'IdentityUserLogin<string>' requires a primary key to be defined

C#Entity Frameworkasp.net Coreasp.net Identity

C# Problem Overview


i am using dotnet core 1.1 on linux, and i am having issues when i want to split up the identityContext from my regular dbContext, whenever i run the following line in my startup.cs --> configure:

//... some other services
using (var serviceScope = app.ApplicationServices.GetRequiredService<IServiceScopeFactory>().CreateScope())
{
    serviceScope.ServiceProvider.GetService<ApplicationDbContext>().Database.Migrate();
    //running other database.migrations here + seeding data. But it is the line above that causes problems

So this line throws the exception: The entity type 'IdentityUserLogin' requires a primary key to be defined

I simply don't understand this, why is it my job to give the IdentityUserLogin a primary key??, it is a 3rd party class and i haven't even touched it. I have the following simple setup:

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

        public ApplicationDbContext()
        {

        }

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

            
        }
    }
}

And the applicationUser:

namespace EsportshubApi.Models.Entities
{

    public class ApplicationUser : IdentityUser
    {
        public ApplicationUser() { }

        public static ApplicationUserBuilder Builder()
        {
            return new ApplicationUserBuilder(new ApplicationUser());
        }

        public int AccountId { get; set; }
        public Guid AccountGuid { get; set; }
        public string Salt { get; set; }
        public bool Verified { get; set; }
        public string Checksum { get; set; }
        public string Password { get; set; }
        public DateTime Created { get; set; }
        public DateTime Updated { get; set; }
    }

}

In my startup i am configuring the identity framework the following way:

configureServices:

services.AddEntityFrameworkSqlServer().AddMySQL().AddDbContext<ApplicationDbContext>(options =>
                    options.UseMySQL(config["ConnectionStrings:DefaultConnection"]));

And

Configure:

 app.UseIdentity();

My project is opensourced at : my github repo

if that helps.

I have tried a lot of things. The two most promising was deriving all of the classes used in this generic show, and passing them in explicitly, tried to change all of their keys to ints etc. And that gave the exact same error just with int instead of string. The other way i tried was to do the following inside of OnModelCreating to give IdentityUserLogin a primary key by e.g :

 modelBuilder.Entity<IdentityUserLogin<int>>()
            .Property(login => login.UserId)
            .ForMySQLHasColumnType("PK")
            .UseSqlServerIdentityColumn()
            .UseMySQLAutoIncrementColumn("AI");

As you can see, this was back when i had UserId as a integer, but i am not even sure if the UserId should be its primaryKey. I can get other errors instead of this one, that says

> IdentityUserLogin is part of a hierarchy, and it has no discriminator values

But if I had discriminator values it eventually just goes back to this error. The weirdest part i think is that i have the EXACT same implementation as the UnicornStore github example, that uses a bit of the identity framework as well .... So i really need your help guys. Can reproduce this error by downloading the project, copying the default.appsettings.json into appsettings.json, put in a valid connectionstring, dotnet restore, run with dotnet run --environment Development.

I even tried to change out the implementation to use a MSSQL database instead of MySQL, but that gave the exact same error.

C# Solutions


Solution 1 - C#

keys of Identity tables are mapped in OnModelCreating method of IdentityDbContext and if this method is not called, you will end up getting the error that you got.

All you need to do is call.

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

The original answer (just copied for other's reference just in case) here

Solution 2 - C#

Okay. So i will try to answer my own question, because i did get past it. Its still possible to follow the github link in the OP, and see the project i got the error in.

Mainly what was wrong, was that i thouth i got this error trying to migrate the ApplicationDbContext : IDentityContext but actually the error was thrown based on my other dbContext in the application, when i tried to run the migration on that one. I am still a little unaware as to why the other DbContext picked up on these Identity entities which i had not referred to anywhere, i think it's odd that a dbcontext seems to know something about entities not mentioned in the OnModelCreating method. Anyway - when i found out that it wasn't the IdentityDbContext that something was wrong with, i simply added the following in the OnModelCreating of the context that threw the error:

 protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);
            modelBuilder.Ignore <IdentityUserLogin<string>>();
            modelBuilder.Ignore <IdentityUserRole<string>>();
            modelBuilder.Ignore<IdentityUserClaim<string>>();
            modelBuilder.Ignore<IdentityUserToken<string>>();
            modelBuilder.Ignore<IdentityUser<string>>();
            modelBuilder.Ignore<ApplicationUser>();

So ... i am still wondering why my context is picking up on these entities without having anything to do with them, and i am pretty worried that each time i add a context i have to exclude models in contrary to including them.

Solution 3 - C#

I had a similar issue relating to your initial problem where

> The entity type 'IdentityUserLogin' requires a primary key to > be defined.

And while I think your solution to ignore entities seems to work, I just wanted to provide another solution for those who actually do want to assign a primary key to each entity. The problem is that whenever you create an entity, the DbContext will want keep track of the primary key for each - thus, you'd have to assign it.

See my example below, where Project and Target are my entities, and I've assigned it each a property I would like to use as the primary key for each entity.

protected override void OnModelCreating(ModelBuilder builder)
{
    builder.Entity<Project>().HasKey(m => m.ProjectPath);
    builder.Entity<Target>().HasKey(m => m.Guid);
    base.OnModelCreating(builder);
} 

After you've identified and assigned which property should be designated as the primary key for that entity, the error will go away.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionDenLilleMandView Question on Stackoverflow
Solution 1 - C#immirzaView Answer on Stackoverflow
Solution 2 - C#DenLilleMandView Answer on Stackoverflow
Solution 3 - C#susieloo_View Answer on Stackoverflow