Search code examples
c#sqlentity-frameworkasp.net-coreasp.net-identity

Entity Framework Core "The entity type 'XXX' requires a primary key to be defined."


So I'm currently trying to create a code first migration with Entity Framework Core for a table that displays which lectures the application user has completed. My model looks like this:

public class LectureCompletion
{
    [Key,  Column(Order = 0)]
    [ForeignKey("Lecture")]
    public Lecture LectureId { get; set; }

    [Key,  Column(Order = 1)]
    [ForeignKey("User")]
    public ApplicationUser UserId{ get; set; }

    public bool Completed { get; set; }
}

I want to use the UserId and the LectureId as the unique composite key. However I get this error:

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

I don't understand why this is happening as I clearly have my key attributes in the correct positions? Am I able to use ApplicationUser as foreign/primary key?

Here is my Lecture model:

public class Lecture
{
    [Key]
    public int LectureId { get; set; }

    public string ModuleName { get; set; }
    public string LectureName { get; set; }
}

And my ApplicationDBContext.cs:

public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
    public DbSet<Lecture> Lectures { get; set; }
    public DbSet<LectureCompletion> LectureCompletion { get; set; }

    public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
        : base(options)
    {
    }

    protected override void OnModelCreating(ModelBuilder builder)
    {
        base.OnModelCreating(builder);
        // Customize the ASP.NET Identity model and override the defaults if needed.
        // For example, you can rename the ASP.NET Identity table names and more.
        // Add your customizations after calling base.OnModelCreating(builder);
    }
}

Solution

  • You can't define a composite key with data annotation alone. You need to use Fluent API instead.

    public class LectureCompletion
    {
        // which is your case.
        [ForeignKey(nameof(Lecture))] 
        public int LectureId { get;set; }
        public Lecture Lecture { get; set; }
        [ForeignKey(nameof(ApplicationUser))]
        public int UserId {get;set;}
        public ApplicationUser ApplicationUser { get; set; }
        public bool Completed { get; set; }
    }
    
    
    protected override void OnModelCreating(ModelBuilder builder)
    {
         base.OnModelCreating(builder);
    
         // Define composite key.
         builder.Entity<LectureCompletion>()
             .HasKey(lc => new { lc.LectureId, lc.UserId });
    }
    

    https://learn.microsoft.com/en-us/ef/core/modeling/keys