Many-many relationship in Entity Framework Code First and using the “virtual” keyword to access each other

前端 未结 2 1002
夕颜
夕颜 2021-01-06 08:19

This excerpt code successfully creates a many-many relationship with an explicit Junction table that has additional data within it.

PROBLEM:

相关标签:
2条回答
  • 2021-01-06 08:30

    Entity Framework can't automatically determine 'many-to-many' relations because they are expressed with the help of additional tables in SQL (in your case it is Enrollment table). You can specify mappings directly in OnModelCreating method:

    public class YourDbContext : DbContext
    {
        ....
    
        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Student>().HasMany(x => x.Courses).WithMany(x => x.Students)
                .Map(m =>
                {
                    m.ToTable("Enrollment"); // Relationship table name
                    m.MapLeftKey("StudentID"); // Name of column for student IDs
                    m.MapRightKey("CourseID"); // Name of column for course IDs
                });
        }
    }
    

    Also, take a note that if an entity have many other entities, use collection for relationship:

    public class Student
    {
        ....
        public virtual ICollection<Course> Courses { get; set; } // Many courses
    }
    
    public class Course
    {
        ....
        public virtual ICollection<Student> Students { get; set; } // Many students
    }
    
    0 讨论(0)
  • 2021-01-06 08:43
    public class Student
    {
        public virtual int StudentId { get; set; }
        public virtual string StudentName { get; set; }
    
        public virtual ICollection<Enrollment> Enrollments { get; set; }
    }
    
    public class Course
    {
        public virtual int CourseId { get; set; }
        public virtual string CourseName { get; set; }
    
        public virtual ICollection<Enrollment> Enrollments { get; set; }
    }
    
    public class Enrollment
    {
        public virtual int StudentId { get; set; }
        public virtual int CourseId { get; set; }
        public virtual string Grade { get; set; }
    
        public virtual Student Student { get; set; }
        public virtual Course Course { get; set; }
    }
    
    public class ManyMany : DbContext
    {
        public DbSet<Student> Students { get; set; }
        public DbSet<Course> Courses { get; set; }
        public DbSet<Enrollment> Enrollments { get; set; }
    
        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Student>()
                .HasKey(student => student.StudentId);
            modelBuilder.Entity<Course>()
                .HasKey(course => course.CourseId);
            modelBuilder.Entity<Enrollment>()
                .HasKey(enrollment => new { enrollment.StudentId, enrollment.CourseId } );
    
            modelBuilder.Entity<Student>()
                .HasMany(student => student.Enrollments)
                .WithRequired(enrollment => enrollment.Student)
                .HasForeignKey(enrollment => enrollment.StudentId);
            modelBuilder.Entity<Course>()
                .HasMany(course => course.Enrollments)
                .WithRequired(enrollment => enrollment.Course)
                .HasForeignKey(enrollment => enrollment.CourseId);
        }
    }
    

    Older question concerning this, answer and more info here: Entity Framework CodeFirst many to many relationship with additional information.

    EDIT: Usage example:

        var context = new ManyMany();
    
        var physicsCourse = new Course() { CourseName = "Physics" };
        var mathCourse = new Course() { CourseName = "Math" };
    
        var studentJohn = new Student() { StudentName = "John Doe" };
        var studentJane = new Student() { StudentName = "Jane Doe" };
    
        var physicsCourseEnrollmentJohn = new Enrollment() { Student = studentJohn, Course = physicsCourse };
        var mathCourseEnrollmentJohn = new Enrollment() { Student = studentJohn, Course = mathCourse };
        var physicsCourseEnrollmentJane = new Enrollment() { Student = studentJane, Course = physicsCourse };
    
        context.Courses.Add(physicsCourse);
        context.Courses.Add(mathCourse);
        context.Students.Add(studentJohn);
        context.Students.Add(studentJane);
    
        studentJohn.Enrollments.Add(physicsCourseEnrollmentJohn);
        studentJohn.Enrollments.Add(mathCourseEnrollmentJohn);
        studentJane.Enrollments.Add(physicsCourseEnrollmentJane);
    
        physicsCourse.Enrollments.Add(physicsCourseEnrollmentJohn);
        mathCourse.Enrollments.Add(mathCourseEnrollmentJohn);
        physicsCourse.Enrollments.Add(physicsCourseEnrollmentJane);
    
        context.Enrollments.Add(physicsCourseEnrollmentJohn);
        context.Enrollments.Add(mathCourseEnrollmentJohn);
        context.Enrollments.Add(physicsCourseEnrollmentJane);
    
        context.SaveChanges();
    
        var johnsEnrollments = context.Students.Where(student => student.StudentId == studentJohn.StudentId).Single().Enrollments;
        MessageBox.Show(string.Format("Student John has enrolled in {0} courses.", johnsEnrollments.Count));
        var janesEnrollments = context.Students.Where(student => student.StudentId == studentJane.StudentId).Single().Enrollments;
        MessageBox.Show(string.Format("Student Jane has enrolled in {0} courses.", janesEnrollments.Count));
    
    0 讨论(0)
提交回复
热议问题