多对多关系 many to many

一个学生可以上多个课程,在数据库当中我们一般会定义成三个表,学生表 Student,课程表 Course,学生课程表StudentCourse。 学生课程表,这个表东西就是用来存储学生和课程的关系。因为一个学生可以上多个课程,反过来说就是一门课程也有很多学生参加。

在EF core中我们有两种方式来实现这种多对多的关系。

第一种 不定义中间表 实体类的 的方式

public class Student 
{
    public int Id { get; set; }

    public string Name { get; set; }

// 一个学生有多个课程
    public ICollection<Course> Courses { get; set; } 
}

public class Course
{
    public int Id { get; set; }

    public string Name { get; set; }
//一个课程有多个学生
    public ICollection<Student> Students { get; set; } 
}

 public class MalemaDbContext : DbContext
    {
        public MalemaDbContext(DbContextOptions<MalemaDbContext> options)
            : base(options)
        {
            this.Database.EnsureCreated();
        }

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

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

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Student>().Property(x => x.Name).HasMaxLength(50);
            
            base.OnModelCreating(modelBuilder);
        }
    }

上面代码会自动生成三张表 Students, Courses, 还有 CourseStudents.

但是因为多对多哪张表我们没有显式定义出来,所以对数据库的一些操作会变得比较不方便。 对于关系表我们没有办法单独删除。 可以通过下面的方式来添加数据

public class ManyToManyExample
    {
        private readonly MalemaDbContext malemaDbContext;
        private readonly IDbContextFactory<MalemaDbContext> dbContextFactory;

        public ManyToManyExample(MalemaDbContext malemaDbContext, IDbContextFactory<MalemaDbContext> dbContextFactory)
        {
            this.malemaDbContext = malemaDbContext;
            this.dbContextFactory = dbContextFactory;
        }

        public void InitData()
        {
            using (var dbContext = this.dbContextFactory.CreateDbContext())
            {
                if (dbContext.Students.Count() < 1)
                {
                    var courses = GetCourses();
                    dbContext.AddRange();

                    dbContext.SaveChanges();
                    var students = GetStudents();
                    foreach (var item in students)
                    {
                        item.Courses = courses;
                    }
                    dbContext.AddRange(students);
                    dbContext.SaveChanges();
                }
            }
        }

        private static List<Course> GetCourses()
        {
            var course1 = new Course() { Name = "英语" };
            var course2 = new Course { Name = "足球" };

            return new List<Course>() { course1, course2 };
        }

        private static List<Student> GetStudents()
        {
            var student1 = new Student() { Name = "张三", };
            var student2 = new Student() { Name = "李四", };


            return new List<Student>() { student1, student2 };
        }
    }

上面的完整代码可以在分支relationship/many_to_many_1看到

git clone https://gitee.com/malema/Examples
git checkout relationship/many_to_many_1

ManyToManyExample.cs

第二种 定义一个中间表的实体类 StudentCourse

    public class Course
    {
        public int Id { get; set; }

        public string Name { get; set; }

        public ICollection<StudentCourse> StudentCourses { get; set; } 
    }
    
    public class Student 
    {
        public int Id { get; set; }

        public string Name { get; set; }

        public ICollection<StudentCourse> StudentCourses { get; set; }
    }
    
    public class StudentCourse
    {
        public int Id { get; set; }

        public int StudentId { get; set; }

        public int CourseId { get; set; }

        public Student Student { get; set; }

        public Course Course { get; set; }
    }

    public class MalemaDbContext : DbContext
    {
        public MalemaDbContext(DbContextOptions<MalemaDbContext> options)
            : base(options)
        {
            this.Database.EnsureCreated();
        }

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

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

        public DbSet<StudentCourse> StudentCourses { get; set; }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Student>().Property(x => x.Name).HasMaxLength(50);
            
            base.OnModelCreating(modelBuilder);
        }
    }

上面代码会同样会生成三张表 Students, Courses, 还有 CourseStudents.

我们可以通过下面的这种方式来添加数据。 因为多对多表也会单独的映射。所以我们可以很方便只对关系进行操作。

public class ManyToManyExample
    {
        private readonly MalemaDbContext malemaDbContext;
        private readonly IDbContextFactory<MalemaDbContext> dbContextFactory;

        public ManyToManyExample(MalemaDbContext malemaDbContext, IDbContextFactory<MalemaDbContext> dbContextFactory)
        {
            this.malemaDbContext = malemaDbContext;
            this.dbContextFactory = dbContextFactory;
        }

        public void InitData()
        {
            using (var dbContext = this.dbContextFactory.CreateDbContext())
            {
                if (dbContext.Students.Count() < 1)
                {
                    var courses = GetCourses();
                    dbContext.AddRange(courses);
                    dbContext.SaveChanges();
                    
                    var students = GetStudents();
                    dbContext.AddRange(students);
                    dbContext.SaveChanges();

                    var studentCourse1 = new StudentCourse()
                    {
                        StudentId = 1,
                        CourseId = 1,
                    };

                    var studentCourse2 = new StudentCourse()
                    {
                        StudentId = 1,
                        CourseId = 2,
                    };
                    var studentCourse3 = new StudentCourse()
                    {
                        StudentId = 2,
                        CourseId = 1,
                    };

                    dbContext.AddRange(studentCourse1, studentCourse2, studentCourse3);
                }
            }
        }

        private static List<Course> GetCourses()
        {
            var course1 = new Course() { Name = "英语" };
            var course2 = new Course { Name = "足球" };

            return new List<Course>() { course1, course2 };
        }

        private static List<Student> GetStudents()
        {
            var student1 = new Student() { Name = "张三", };
            var student2 = new Student() { Name = "李四", };


            return new List<Student>() { student1, student2 };
        }
    }

上面的完整代码可以在分支relationship/many_to_many_2看到

git clone https://gitee.com/malema/Examples
git checkout relationship/many_to_many_2

ManyToManyExample.cs

最近更新的
...