0

I'm trying to make many to many relationships between two classes with EF Core fluent API. How can I change the foreign key names of the table between that will be created for this relationship?

For example, if we create a many-to-many relationship between the following two classes:

public class Student
{
    public int StudentId { get; set; }
    public string Name { get; set; }
    public virtual ICollection<Course> Courses { get; set; }
}

public class Course
{
    public int CourseId { get; set; }
    public string CourseName { get; set; }
    public string Description { get; set; }

    public virtual ICollection<Student> Students { get; set; }
}

// Fluent Api
public class UserMap : IEntityTypeConfiguration<User>
{
    public void Configure(EntityTypeBuilder<User> builder)
    {
        builder.HasKey(x => x.Id);
        builder.ToTable("Users");

        builder.HasMany<Course>(user => user.Courses)
               .WithMany(course => course.Users);
    }
}

A table is created like this:

enter image description here

What I want is to create the in-between table with the foreign key names I give during code-first.

I know I can write the in-between table as a class and change the names with a one-to-many relationship, but I want to do it with code-first.

Example taken from EF core documentation.

Ali Yıldızöz
  • 389
  • 2
  • 12
  • I believe you can add .HasForeignKey("ForeignKeyName") after .WithMany(). Replace "ForeignKeyName" with the name you want. See https://learn.microsoft.com/en-us/ef/core/modeling/relationships?tabs=fluent-api%2Cfluent-api-simple-key%2Csimple-key#manual-configuration shadow foreign key – Marco Sep 05 '21 at 10:30
  • No I can't, also even if I could, there are two foreign keys there, I can rename which one with HasForeignkey function. – Ali Yıldızöz Sep 05 '21 at 10:46

1 Answers1

2

You might want to add a new class for the in-between table:

public class StudentCourse
{
    public int FKStudentId { get; set; }
    public int FKCourseId { get; set; }

    public virtual Student Student { get; set; }
    public virtual Course Course { get; set; }

}

and replace the navigation properties:

public virtual ICollection<Course> Courses { get; set; }

with

public virtual ICollection<StudentCourse> Courses { get; set; }

do the same in the Course class.

Then in the fluent Api, you can you now use the new class.

public class StudentConfiguration : IEntityTypeConfiguration<Student>
{
    public void Configure(EntityTypeBuilder<Student> entity)
    {
        entity.HasKey(x => x.StudentId);

        entity.HasMany(student => student.Courses)
            .WithOne(course => course.Student)
            .HasForeignKey(x => x.FKStudentId);

    }
}

public class CourseConfiguration : IEntityTypeConfiguration<Course>
{
    public void Configure(EntityTypeBuilder<Course> entity)
    {
        entity.HasKey(x => x.CourseId);

        entity.HasMany(course => course.Students)
            .WithOne(stud => stud.Course)
            .HasForeignKey(x => x.FKCourseId);

    }
}

EDIT: If you don't want to add in-between class, you may want to try this:

        entity.HasMany(student => student.Courses)
            .WithMany(course => course.Students)
            .UsingEntity(x => x.Property("StudentsStudentId").HasColumnName("FKStudentId"));

        entity.HasMany(course => course.Students)
            .WithMany(stud => stud.Courses)
            .UsingEntity(x => x.Property("CoursesCourseId").HasColumnName("FKCourseId"));

Note: "StudentsStudentId" and "CoursesCourseId" are generated by naming convention. So you may want to add migration first without the .UsingEntity() and inspect the generated migration.

rjs123431
  • 688
  • 4
  • 14