FluentAPI 一对多,多对多


一对多

模型

Nationality(国家)数据模型(对应“一”) 因为已过国家有很多人,而一个人只能有一个国家

namespace BF.Entities.Entitys
{
    /// <summary>
    /// 国家
    /// </summary>
    public class Nationality
    {
        public int Id { get; set; }
        /// <summary>
        /// 国家名称
        /// </summary>
        public string Name { get; set; }
        /// <summary>
        /// 简称
        /// </summary>
        public string Abbre { get; set; }
        /// <summary>
        /// 人的导航属性(一个国家里面有很多人)
        /// </summary>
        public virtual ICollection<Person> Persons { get; set; }
    }
}

Person(人)数据模型 (对应“多”)

namespace BF.Entities.Entitys
{
    /// <summary>
    /// 人
    /// </summary>
    public class Person
    {
        public int Id { get; set; }
        /// <summary>
        /// 姓名
        /// </summary>
        public string Name { get; set; }
        /// <summary>
        /// 年龄
        /// </summary>
        public int Age { get; set; }
        /// <summary>
        /// 所属国家国家编号
        /// </summary>
        public int NationalityId { get; set; }

        /// <summary>
        /// 国家导航属性(一个人只能属于一个国家)
        /// </summary>
        public virtual Nationality Nationality { get; set; }
    }
}

数据模型配置文件

NationalityConfig文件

namespace BF.Entities.EntityConfig
{
    class NationalityConfig:EntityTypeConfiguration<Nationality>
    {
        public NationalityConfig()
        {
            this.ToTable("T_Nationality").HasKey(r => r.Id);
            this.Property(r => r.Id).HasDatabaseGeneratedOption(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.Identity);//设置Id是自动增长类型的

            //注意:在一对多关系中,Nationality对应的是“一” 关系配置应该在“多”端进行配置,如果在“多”端进行配置了这里可以不配置
            //当然配置了也没关系。

            //this表示Nationality国家这个数据模型
            //this.HasMany(r => r.Persons)表示一个国家中有很多人
            //.WithRequired(r => r.Nationality)是跟在HasMany(r => r.Persons)后面的,表示一个只能属于一个国家
            //.HasForeignKey(r => r.NationalityId)表示T_Nationality与T_Person表之间关联的外键是T_Person表中的NationalityId属性
            this.HasMany(r => r.Persons).WithRequired(r => r.Nationality).HasForeignKey(r => r.NationalityId);
        }
    }
}
PersonConfig文件
namespace BF.Entities.EntityConfig
{
    public class PersonConfig:EntityTypeConfiguration<Person>
    {
        public PersonConfig()
        {
            this.ToTable("T_Person").HasKey(r => r.Id);
            this.Property(r => r.Id).HasDatabaseGeneratedOption(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.Identity);//设置Id是自动增长类型的

            //一对多,一般是在“多”这一方进行配置 
            //(国家对人,一个人只能属于一个国家,而一个国家可以有多个人,所以国家是“一”,人是“多”)

            //这个this就表示Person 
            //this.HasRequired(r => r.Nationality)表示这个人,只能一定只能属于一个国家
            //his.HasRequired(r => r.Nationality).WithMany(r => r.Persons)表示这个人只能一定只能属于一个国家,而国家有多个人
            //.HasForeignKey(r => r.NationalityId)表示T_Person表与T_Nationality表关联的外键是T_Person表的NationalityId属性
            this.HasRequired(r => r.Nationality).WithMany(r => r.Persons).HasForeignKey(r => r.NationalityId);
        }
    }
}


EF上下文容器类

在OnModelCreating方法中,将数据模型配置文件加入到DbModelBuilder容器中,这样就可以使用这个配置文件了

namespace BF.Entities
{
    public class BFDbContext : DbContext
    {
        public BFDbContext()
            : base("name=ConnStr")
        {
            base.Database.CreateIfNotExists();         
           
        }
        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);

            //将模型配置文件加入到DbModelBuilder中
            modelBuilder.Configurations.AddFromAssembly(
                Assembly.GetExecutingAssembly());         
        }

        public DbSet<Nationality> Nationality { get; set; }
        public DbSet<Person> Person { get; set; }
    }
}

使用(控制器类)

namespace WebApp.Controllers
{
    using System.Data.Entity;// 如果要在IQueryable接口中使用Include就如要引入它
    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            BFDbContext db = new BFDbContext();

            Nationality cn = new Nationality() { Name = "中国", Abbre = "CN" };
            Nationality us = new Nationality() { Name = "美国", Abbre = "US" };

            //注意这里要给Person类的导航属性赋值,NationalityId属性不用赋值
            Person cnP = new Person() { Name = "毛泽东", Age = 86, Nationality = cn };
            Person usP = new Person() { Name = "克林顿", Age = 86, Nationality = us };

            //如果仅仅是添加这国家的数据的话,就无法把人添加到Person表了,
            //db.Nationality.Add(cn);
            //db.Nationality.Add(us); 

            //我们应该这样做(因为cnP,和usP中已经把这两个人添加了他们的国家了,所以执行这两段代码后,T_Person和T_Nationality都会被添加数据)
            db.Person.Add(cnP);
            db.Person.Add(usP);

            db.SaveChanges();

            //Include只能用于导航属性的联合查询,他的参数是导航属性的名称
            var a = db.Person.Where(r => r.Id == 1).Include("Nationality").SingleOrDefault();
            var b = db.Nationality.First().Persons.ToList();

            return View();
        }
    }
}

我们可以看到数据库中生成了三张表, __MigrationHistory表我们不用去管它(T_Nationality国家表,T_Person 人表)


T_Nationality国家表


T_Person 人表


多对多

数据模型

Teacher(老师)模型类 (多对多关系中对应“多”)一个老师可以有多个学生,而一个学生也可以有多个老师,所以Teacher属于“多”

namespace BF.Entities.Entitys
{
    //老师表
    public class Teacher
    {
        public Teacher()
        {
            this.Students = new HashSet<Student>();
        }    
        public int Id { get; set; }

        public string Name { get; set; }

        public int Age { get; set; }
        /// <summary>
        /// 老师表中有多个学生,所以是Students
        /// </summary>
        public virtual ICollection<Student> Students { get; set; }
    }
}

Student(学生)模型类(多对多关系中对应“多”)一个老师可以有多个学生,而一个学生也可以有多个老师,所以Student也属于“多”

namespace BF.Entities.Entitys
{
    //学生表
    public class Student
    {
        public Student()
        {
            this.Teachers = new HashSet<Teacher>();
        }
        public int Id { get; set; }
        public string Name { get; set; }
        public int Age { get; set; }
        /// <summary>
        /// 学生可以有多个老师,所以这里是Teachers
        /// </summary>
        public virtual ICollection<Teacher> Teachers { get; set; }
    }
}

数据模型配置文件

TeacherConfig文件

namespace BF.Entities.EntityConfig
{
    public class TeacherConfig : EntityTypeConfiguration<Teacher>
    {
        public TeacherConfig()
        {
            this.ToTable("T_Teacher").HasKey(r => r.Id);
            this.Property(r => r.Id).HasDatabaseGeneratedOption(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.Identity);//设置Id是自动增长类型的

            //多对多关系配置,只要在其中一方进行配置就行了。不需要两边都进行配置,所以在TeacherConfig中配置了,就不需要在StudentConfig中再进行配置了。反过来也一样(反正只配置一方,在哪方配置都行)

            //this表示Teacher这个模型类,表示T_Teacher表
            //this.HasMany(r => r.Students)表示老师中有多个学生
            //.WithMany(r => r.Teachers)是跟在HasMany(r => r.Students)后面的,表示学生有多个老师

            //Map表示关系映射
            //(r => r.ToTable("T_TeacherStudentRelations")表示这两个表生成的关系映射表名称叫T_TeacherStudentRelations
            //.MapLeftKey("TeacherId") 表示这个关系映射表的左边字段(第一个字段)名称叫TeacherId(因为关系映射表就两个字段)
            //.MapRightKey("StudentId") 表示这个关系映射表的右边字段(第二个字段)名称叫StudentId (因为关系映射表就两个字段)
            //注释:因为this表示Teacher 它在前面,所以它是左,而Student对于的就是右了。
            this.HasMany(r => r.Students).WithMany(r => r.Teachers).Map(r => r.ToTable("T_TeacherStudentRelations").MapLeftKey("TeacherId").MapRightKey("StudentId"));
        }
    }
}

StudentConfig文件

namespace BF.Entities.EntityConfig
{
    public class StudentConfig : EntityTypeConfiguration<Student>
    {
        public StudentConfig()
        {
            this.ToTable("T_Student").HasKey(r => r.Id);
            this.Property(r => r.Id).HasDatabaseGeneratedOption(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.Identity);//设置Id是自动增长类型的
        }
    }
}

EF上下文容器类

在OnModelCreating方法中,将数据模型配置文件加入到DbModelBuilder容器中,这样就可以使用这个配置文件了

namespace BF.Entities
{
    public class BFDbContext : DbContext
    {
        public BFDbContext()
            : base("name=ConnStr")
        {
            base.Database.CreateIfNotExists();         
           
        }
        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);

            //将模型配置文件加入到DbModelBuilder中
            modelBuilder.Configurations.AddFromAssembly(
                Assembly.GetExecutingAssembly());         
        }

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

控制器中使用

namespace WebApp.Controllers
{
    using System.Data.Entity;// 如果要在IQueryable接口中使用Include就如要引入它
    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            BFDbContext db = new BFDbContext();

            Student s1 = new Student() { Name = "张三", Age = 15 };
            Student s2 = new Student() { Name = "李四", Age = 16 };
            Teacher t1 = new Teacher() { Name = "李老师", Age = 35 };
            Teacher t2 = new Teacher() { Name = "王老师", Age = 36 };

            //给张老师添加2个学生(张三,李四)
            t1.Students.Add(s1);
            t1.Students.Add(s2);

            //王老师只有一个学生(张三)
            t2.Students.Add(s1);

            //添加2个老师(两个学生可以不添加,他会自动添加)
            db.Teacher.Add(t1);
            db.Teacher.Add(t2);

            //这两段代码可以不添加,如果要这两段代码就不要上面的那两段代码
            //db.Student.Add(s1);
            //db.Student.Add(s2);

            
            db.SaveChanges();            
            return View();
        }
    }
}
我们可以看到数据库中生成了4个表,__MigrationHistory表我们不用去管他(T_Student学生表,T_Teacher老师表,T_TeacherStudentRelations老师,学生关系映射表)

T_Teacher老师表


T_Student学生表


T_TeacherStudentRelations老师,学生关系映射表


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值