How do you model a many-to-many relationship in EF Core?

Entity Framework & EF Core Modelling Intermediate 1–2 Yrs2–3 Yrs Conceptual 1 min read

Quick Answer

Since EF Core 5 you can declare a collection on each side (Student.Courses, Course.Students) and EF creates the join table implicitly — skip navigations. If the relationship carries data (a grade, an enrolment date), you model an explicit join entity (Enrolment) with two one-to-many relationships.

From EF Core 5 onwards, if it's a plain link — students and courses with nothing extra — I just put a List<Course> on Student and a List<Student> on Course, and EF generates the join table for me. Those are skip navigations. If the link itself has data — a grade, an enrolment date — then I create an explicit Enrolment entity with a foreign key to each side and two one-to-many relationships, and I navigate through that. Before EF Core 5 you always had to hand-write the join entity even for the plain case.

  • Pure link: just the two collection properties; EF makes CourseStudent. Customise the join table with UsingEntity(...).
  • With payload: explicit Enrolment { StudentId, CourseId, Grade, EnrolledOn }; navigate Student.Enrolments → Enrolment.Course.
  • Pre-EF Core 5 you always had to write the join entity by hand.
  • Querying skip navigations: db.Students.Include(s => s.Courses).