2

I'm trying to setup some navigation properties with some Entity Framework Code First models. I'd like them to look like this example:

public class Course
{
    [Key]
    public int CourseId { get; set; }
    public string CourseName { get; set; }
    public virtual ICollection<Student> Students { get; set; }
}

public class Student
{
    [Key]
    public int StudentId { get; set; }
    public string StudentName { get; set; }
    public virtual ICollection<Course> Courses { get; set; }
}

public class StudentCourses
{
    [Key, Column(Order = 0)]
    public int StudentId { get; set; }
    public virtual Student Student { get; set; }
    [Key, Column(Order = 1)]
    public int CourseId { get; set; }
    public virtual Course Course { get; set; }
}

So Student and Course relationships would be established in the StudentCourses table. An instance of the student class would automatically reference all of that students courses, and vice versa an instance of the Course class would automatically reference all of its Students. And an instance of the StudentCourses class would automatically reference its Student and Course. But when I try to Update-Database, the relationships don't seem to get properly interpreted. Is there anything I'm missing here? Perhaps some configuring needs to be done in the context class? Most of the examples of navigation properties just show one-to-many relationship navigation properties.

2 Answers 2

2

You need to construct your models as shown below when you have a M : M relationship. You don't need to construct junction table. EF will create one for you when you do the data migration.

Model configuration using Conventions.

public class Student
{
    public Student() 
    {
        this.Courses = new HashSet<Course>();
    }

    public int StudentId { get; set; }

    public string StudentName { get; set; }

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

public class Course
{
    public Course()
    {
        this.Students = new HashSet<Student>();
    }

    public int CourseId { get; set; }
    public string CourseName { get; set; }

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

Your context class should be like this.

public class YourDBContext : DBContext
{
    public YourDBContext () : base("Default")
    {
    }

    public DbSet<Student> Students { get; set; }

    public DbSet<Course> Courses { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);
    }
}
Sign up to request clarification or add additional context in comments.

2 Comments

Ah, so EF abstracts away that table completely from the model. I thought I would need to have a class for the junction table EF creates, but I suppose the navigation properties make that unnecessary.
Yes,EF will create a junction table for you.You don't need to do it manually.
1

After following Sampath's advice, I actually decided I wanted to attach some other properties to the relationship. So I ended up defining the StudentCourses class afterall like this:

public class StudentCourses
{
    [Key, Column(Order = 0)]
    public int StudentId { get; set; }
    public virtual Student Student { get; set; }
    [Key, Column(Order = 1)]
    public int CourseId { get; set; }
    public virtual Course Course { get; set; }
    public int Grade { get; set; }
}

So I changed Student and Course like this:

public class Course
{
    [Key]
    public int CourseId { get; set; }
    public string CourseName { get; set; }
    public virtual ICollection<StudentCourses> Students { get; set; }
}

public class Student
{
    [Key]
    public int StudentId { get; set; }
    public string StudentName { get; set; }
    public virtual ICollection<StudentCourses> Courses { get; set; }
}

And most importantly, I did not add StudentCourses to the DbContext. So after Update-Database was performed, EF automatically created the table for StudentCourses, and the navigation properties all work.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.