Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

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);
    }
}
like image 312
Josh L Avatar asked Jun 21 '17 02:06

Josh L


2 Answers

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

like image 60
anserk Avatar answered Sep 24 '22 08:09

anserk


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.

like image 20
IvanJazz Avatar answered Sep 21 '22 08:09

IvanJazz