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

asp.net-core asp.net-identity c# entity-framework sql

Question

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);
    }
}
1
11
6/21/2017 2:58:34 AM

Accepted Answer

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://docs.microsoft.com/en-us/ef/core/modeling/keys

20
3/17/2020 11:47:58 AM

Popular Answer

Your LectureCompletion class needs a primary key to be defined properly.[Key] is the primary key annotation to explicitly tell EntityFramework to set this as your primary key, else convention will take over.

That is, properties that is either named ID or suffixed with ID e.g. PokemonID for Pokemon table. ID or Id is not case sensitive in this case.

The foreign key attribute is only used only if you want your foreign key property name in LectureCompletion class named differently than your referred class. For example, if your ApplicationUser class' primary key is ApplicationUserId, but in LectureCompletion class you want it to be UserId then you can add the attribute.

Do it like this

public class LectureCompletion
{
    [Key] // Defined only once
    public LectureCompletionId { get;set; }

    // Not needed if Lecture class has the primary key property of LectureId,
    // which is your case.
    [ForeignKey("Lecture")] // Name of your navigation property below.
    public int LectureId { get;set; }

    public Lecture Lecture { get; set; }

    [ForeignKey("ApplicationUser")]
    public int UserId {get;set;}

    public ApplicationUser ApplicationUser { get; set; }

    public bool Completed { get; set; }
}

As for EntityFramework Core, the ColumnOrder doesn't appear to have any effect as of now.



Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow