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

66,227

Solution 1

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

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

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.

Share:
66,227
DenLilleMand
Author by

DenLilleMand

Updated on August 21, 2020

Comments

  • DenLilleMand
    DenLilleMand almost 4 years

    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.

  • Jeppe
    Jeppe over 7 years
    Isn't it because you're extending an IdentityDbContext, which up the hierarchy contains the DbSets you're now ignoring?
  • DenLilleMand
    DenLilleMand about 7 years
    I don't exactly remember now, but i do think it was something like that. The context did refer to them in some way.
  • SeriousM
    SeriousM almost 6 years
    I was overwriting it without calling the base, thank you!
  • DenLilleMand
    DenLilleMand almost 6 years
    Okay, so i accept this answer instead of my own, even though in my case i already had that line, and it did not fix it. This clearly seems like what fixes it for a lot of people given the error i explained.
  • SimonGoldstone
    SimonGoldstone over 5 years
    Saved the day for me
  • Chdid
    Chdid over 4 years
    I had a similar case, the issue was i missed from config files not added to OnModelCreating. Once i added them, it all worked out. – Chdid just now Edit
  • Nabeel
    Nabeel over 4 years
    In my case when i added base.OnModelCreating(modelBuilder); it starting throwing sql exception of AspnetRoles not exist. So I had to add migrations and update-database to make it work.
  • mRizvandi
    mRizvandi about 3 years
    If some entity from IdentityDatabaseContext exist in other DatabaseContext, EF create all entities from both database context in main database context! <Find Same DbSet from both DatabaseContext, and remove it>.
  • Admdebian
    Admdebian almost 2 years
    Best answer. This doesn't ignore subclass logic.