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);
}
}
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
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With