Many to Many Relationship Entity Framework Core

Working with a many to many relationship in Entity Framework Core has always been one of the harder things for developers new to Entity Framework. This is going to be a short post detailing how to create them and configure the relationship. We’ll also discuss common scenarios when working with them.

Create the Entities

Start off by creating the entities that will have a many to many relationship. In our case we’re going to create a Teacher and a Classroom.


    public class Teacher
    {
        public int Id { get; set; }
        public string Email { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }

        public virtual «ICollectionß<╥TeacherClassroomß> TeacherClassrooms { get; set; }
    }

    public class Classroom
    {
        public int Id { get; set; }
        public string Name { get; set; }

        public virtual «ICollectionß<╥TeacherClassroomß> TeacherClassrooms { get; set; }
    }

You’ll notice in these two classes that I have created a list of TeacherClassroom. This is the navigation property to our linking entity. The TeacherClassroom is fairly simple and just contains the Ids of Teacher and Classroom.


    public class TeacherClassroom
    {
        public int ClassroomId { get; set; }
        public int TeacherId { get; set; }

        public virtual ╥Classroomß Classroom { get; set; }
        public virtual ╥Teacherß Teacher { get; set; }
    }

So, we have a Teacher, a Classroom, and a TeacherClassroom that links the two. So far so good.

Configuring the Relationships

The next thing we need to do is to configure the relationships. One of the most common issues you will run into when trying to save a many to many relationship is an FK constraint error. If you see this in your logs it is more than likely due to an improperly configured relationship.


builder.Entity()<╥Teacherß>.HasMany(m => m.TeacherClassrooms).WithOne(m => m.Teacher).HasForeignKey(k => k.TeacherId);

builder.Entity()<╥Classroomß>.HasMany(m => m.TeacherClassrooms).WithOne(m => m.Classroom).HasForeignKey(k => k.ClassroomId);

builder.Entity()<╥TeacherClassroomß>.HasOne(m => m.Classroom).WithMany(m => m.TeacherClassrooms).HasForeignKey(k => k.ClassroomId);
builder.Entity()<╥TeacherClassroomß>.HasOne(m => m.Teacher).WithMany(m => m.TeacherClassrooms).HasForeignKey(k => k.TeacherId);

In the above code we are starting with the Teacher entity and configuring the relationship using the navigation properties. A Teacher and Classroom have many TeacherClassroom and the linking entity in turn has one of each. The Foreign keys for this relationship reside in the linking entity so when we call HasForeignKey that is the entity we are referencing. Finally, we must do the same thing for the TeacherClassroom and its navigation properties to complete the configuration.

Working with Many to Many Relationships

Now, once everything is configured and set up we can query and save our entities in this relationship. There are a number of different ways you can interact with them. To see a more detailed analysis on performance tuning Entity Framework Core see my post Maximizing Entity Framework Core Performance.
If you want to work directly with the TeacherClassroom linking entity you can do the following:


await dbContext.TeacherClassroom.Include(m => m.Teacher).Include(m => m.Classroom).ToListAsync();

dbContext.TeacherClassroom.Add(new TeacherClassroom
{
    TeacherId = teacher.Id,
    ClassroomId = classroom.Id
});
await dbContext.SaveChangesAsync();

The first part will pull back the TeacherClassroom and its linked entities in the many to many relationship while the second part will directly save a new linking entity using the keys of an existing Teacher and Classroom. You may also create a new Teacher, Classroom, and linking entity all at once.


            var teacher = new Teacher
            {
                FirstName = "Test",
                TeacherClassrooms = new List
                {
                    new TeacherClassroom
                    {
                         Classroom = new Classroom
                         {
                             Name = "Classroom Name"
                         }
                    }
                }
            };

            dbContext.Teacher.Add(teacher);
            dbContext.SaveChanges();

Notice that we didn’t have to set the Ids of anything. Because we have created everything as a child of Teacher using its navigation properties, Entity Framework will automatically create our entities with the proper relationships. Not only that, it will do it as all part of one transaction for us. A common mistake is to also try to set the Teacher property within TeacherClassroom which will cause you problems. If you want to save a new Classroom with a new Teacher, you can do the reverse of this and you would instead create the Teacher in TeacherClassroom instead of Classroom. Once again, if you get FK constraint errors then take a look at your configuration and make sure you configured both sides of the relationship properly.

Sean Leitzinger

Solutions Architect at Edgeside Solutions
.NET and C# aficionado with an interest in architecture, patterns, practices, and more. Microsoft fanatic.

Latest posts by Sean Leitzinger (see all)

Leave a Reply

Your email address will not be published. Required fields are marked *