Много-много отношений в Entity Framework Code First и использовании «виртуального» ключевого слова для доступа друг к другу - PullRequest
4 голосов
/ 01 апреля 2012

Этот фрагмент кода успешно создает отношение many-many с явной таблицей Junction, в которой есть дополнительные данные.

ПРОБЛЕМА: Я хочу получить доступ к курсам от Студента и наоборот, (следовательно, прокомментированное virtual свойство. Но если я раскомментирую его, оно вызовет ошибку (см. Ниже))

Если я не создаю явно таблицу соединений(без дополнительных данных), виртуальное ключевое слово работает, хотя EF создает таблицу соединений по соглашению.

ВОПРОС:

Как я могу сделать доступ к Курсам для студентов без прохождения регистрации?Или это невозможно?Если это невозможно, то каков наилучший способ сделать это?

( новичок в EF и C # )

    public class Student
    {
        [Key]
        public int StudentId { get; set; }
        public string StudentName { get; set; }

        //public virtual Course Courses { get; set; }
    }

    public class Course
    {
        [Key]
        public int CourseId { get; set; }
        public string CourseName { get; set; }

        //public virtual Student Students { get; set; }
    }

    public class Enrollment
    {
        [Key]
        public int EnrollmentId { get; set; }
        public Student Student { get; set; }
        public Course Course { get; set; }
        public string Grade { get; set; }
    }

    public class ManyMany : DbContext, IContext
    {
        public DbSet<Student> Students { get; set; }
        public DbSet<Course> Courses { get; set; }
        public DbSet<Enrollment> Enrollments { get; set; }

        public void Run()
        {
            Database.SetInitializer(new DropCreateDatabaseAlways<ManyMany1>());
            this.Courses.Add(new Course() {CourseName = "English"});
            this.SaveChanges();
        }
    }

КОГДА Я ОБЯЗАТЕЛЬНОpublic virtual ...

ОШИБКА: "Невозможно определить основной конец ассоциации между типами 'EF.Course' и 'EF.Student'. Основной конец этой ассоциации должен быть явносконфигурирован с использованием API-интерфейса связи или аннотаций данных. "

Ответы [ 2 ]

11 голосов
/ 01 апреля 2012
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);
    }
}

Более старый вопрос по этому вопросу, ответ и дополнительная информация здесь: Entity Framework CodeFirst многие ко многим отношениям с дополнительной информацией .

РЕДАКТИРОВАТЬ: Пример использования:

    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));
5 голосов
/ 01 апреля 2012

Entity Framework не может автоматически определять отношения «многие ко многим», поскольку они выражаются с помощью дополнительных таблиц в SQL (в вашем случае это Enrollment таблица). Вы можете указать сопоставления непосредственно в OnModelCreating методе:

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
            });
    }
}

Кроме того, обратите внимание, что если у сущности есть много других сущностей, используйте коллекцию для отношений:

public class Student
{
    ....
    public virtual ICollection<Course> Courses { get; set; } // Many courses
}

public class Course
{
    ....
    public virtual ICollection<Student> Students { get; set; } // Many students
}
...