One to many 一对多关系

现实的数据关系中经常会出现一对多的关系,比如说一个班级可以有很多的学生,一个校区可能有很多的班级。 我们这边要看的就是EF core 是如何定义这个东西的。

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

        public string Name { get; set; }

        public DateTime BirthDate { get; set; }

//学生的班级Id
        public int? ClassId { get; set; }

        public int Grade { get; set; }

        public decimal TotalScore { get; set; }

        //一个学生有一个班级
        public virtual Class Class { get; set; }

        public override string ToString()
        {
            return $"Id:{Id},Name:{Name},TotalScore:{TotalScore}";
        }
    }

   /// <summary>
    /// 班级
    /// </summary>
    public class Class
    {
        public int Id { get; set; }

        public string Name { get; set; }

 //一个班级的校区Id
        public int? SchoolAreaId { get; set; }
        //一个班级有一个校区, 不弄成virtual也是可以的
        public SchoolArea SchoolArea { get; set; }

        //一个班级有多个学生
        public virtual ICollection<Student> Students { get; set; }
    }

    /// <summary>
    /// 校区
    /// </summary>
    public class SchoolArea
    {
        public int Id { get; set; }

        public string Name { get; set; }

    //一个校区有很多的班级
        public virtual ICollection<Class> Classes { get; set; }

        public static implicit operator SchoolArea(string value)
        {
            return new SchoolArea()
            {
                Name = value
            };
        }
    }

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

//可以看到我们把上面的实体类都加了进来了
        public DbSet<Student> Students { get; set; }

        public DbSet<Class> Classes { get; set; }

        public DbSet<SchoolArea> SchoolAreas { get; set; }

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

会在数据库当中生成三个表

可以用下面的方式来添加数据。

   public void InitData()
        {
            using (var dbCotnext = this.dbContextFactory.CreateDbContext())
            {
                List<Student> students = GetStudents();
                if (dbCotnext.Students.Count() < 1)
                {
                    dbCotnext.SchoolAreas.AddRange(GetSchoolAreas());
                    dbCotnext.SaveChanges();
                    dbCotnext.Classes.AddRange(GetClasses());
                    dbCotnext.AddRange(students);
                    dbCotnext.SaveChanges();
                }
            }
        }

        private static List<SchoolArea> GetSchoolAreas()
        {
            return new List<SchoolArea> { "南区", "北区", "东区" };
        }

        private static List<Class> GetClasses()
        {
            var class1 = new Class() { Name = "104", SchoolAreaId = 1 };
            var class2 = new Class() { Name = "105", SchoolAreaId = 1 };
            var class3 = new Class() { Name = "106", SchoolAreaId = 2 };

            return new List<Class> { class1, class2, class3 };
        }

        private static List<Student> GetStudents()
        {
            var student1 = new Student() { BirthDate = DateTime.UtcNow.AddYears(-12), ClassId = 1, Grade = 2, Name = "张三", TotalScore = 200 };
            var student2 = new Student() { BirthDate = DateTime.UtcNow.AddYears(-13), ClassId = 1, Grade = 2, Name = "李四", TotalScore = 198 };
            var student3 = new Student() { BirthDate = DateTime.UtcNow.AddYears(-13), ClassId = 2, Grade = 2, Name = "王五", TotalScore = 197 };
            var student4 = new Student() { BirthDate = DateTime.UtcNow.AddYears(-13), ClassId = 2, Grade = 2, Name = "赵七", TotalScore = 196 };
            var student5 = new Student() { BirthDate = DateTime.UtcNow.AddYears(-13), ClassId = 2, Grade = 2, Name = "狗蛋", TotalScore = 195 };
            var student6 = new Student() { BirthDate = DateTime.UtcNow.AddYears(-13), ClassId = 2, Grade = 2, Name = "江小牙", TotalScore = 180 };
            //这个学生没有班级
            var student7 = new Student() { BirthDate = DateTime.UtcNow.AddYears(-13), ClassId = null, Grade = 2, Name = "孙小空", TotalScore = 199 };
            return new List<Student>() { student1, student2, student3, student4, student5, student6, student7 };
        }

使用Fluent api进行配置

通常情况下,如果按照规范来写的话,我们是不需要手动进行关系配置的。

但是有需要的话我们也可以手动进行关系配置。

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

            modelBuilder.Entity<Student>()
               .HasOne<Class>(s => s.Class)
               .WithMany(ad => ad.Students)
               //外键的可以是其它的属性名不符合 entity+Id的格式
               .HasForeignKey(x => x.ClassId);

            base.OnModelCreating(modelBuilder);
        }

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

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

OneToManyExample.cs

最近更新的
...