Entity Framework中实体与实体之间的映射关系
在这里,您将了解Entity framework如何管理实体之间的关系。
Entity framework支持三种类型的关系,与数据库一样:1)一对一2)一对多3)多对多。
我们已经在创建实体数据模型一章中为SchoolDB数据库创建了一个实体数据模型。下图显示了该EDM的视觉设计器以及所有实体和它们之间的关系。
让我们看看entity framework是如何管理每个关系(关联)的。
One-to-One(一对一) 关系
正如您在上图中所看到的,Student和StudentAddress具有一对一的关系(0或1)。一个学生只能有一个或零个地址。Entity framework将Student引用导航属性添加到StudentAddress实体中,将StudentAddress导航实体添加到Student实体中。此外,StudentAddress实体同时具有studententid属性作为PrimaryKey(可以不作为主键存在)和ForeignKey(但是一定要作为外键存在,数据加载的时候就是根据该外键来加载数据的),这使它们成为一对一的关系。
public partial class Student
{
public Student()
{
this.Courses = new HashSet<Course>();
}
public int StudentID { get; set; }
public string StudentName { get; set; }
public Nullable<int> StandardId { get; set; }
public byte[] RowVersion { get; set; }
public virtual StudentAddress StudentAddress { get; set; } //关联的另一个实体
}
public partial class StudentAddress
{
//public int ID { get; set; } //默认使用id作为主键或以id结尾的属性作为主键
public int StudentID { get; set; } //关联的Student 表的外键
public string Address1 { get; set; }
public string Address2 { get; set; }
public string City { get; set; }
public string State { get; set; }
public virtual Student Student { get; set; } //关联的另一个实体
}
1、一对一关系,两个实体中都包含对对方的引用导航属性。
2、从属实体中要包含对主体的外键引用(指向主体的主键)。
One-to-Many(一对多) 关系
Standard和Teacher具有一对多的关系,以多重性为标志,其中1代表一个,*代表多个。这意味着Standard可以有多个Teacher,而Teacher只能与一个Standard相关联。
为了表示这一点,Standard实体具有集合导航属性Teachers(请注意它是复数),这表明一个Standard可以有一个Teachers(许多教师)的集合。Teacher实体有一个Standard导航属性(引用属性),它表明Teacher与一个Standard相关联。此外,它还包含了StandardId外键(Standard实体中的PK)。这使其成为一对多关系。
public partial class Standard
{
public Standard()
{
this.Teachers = new HashSet<Teacher>();
}
public int StandardId { get; set; }
public string StandardName { get; set; }
public string Description { get; set; }
public virtual ICollection<Teacher> Teachers { get; set; } //一个等级适用于多个老师
}
public partial class Teacher
{
public Teacher()
{
this.Courses = new HashSet<Course>();
}
public int TeacherId { get; set; }
public string TeacherName { get; set; }
public Nullable<int> TeacherType { get; set; }
public Nullable<int> StandardId { get; set; } //外键,关联等级的主键
public virtual Standard Standard { get; set; } //一个老师对应一个等级
}
Many-to-Many(多对多) 关系
Student和Course具有多对多的关系,其特征是多重性。这意味着一个Student可以注册许多Course,同时,一门Course可以教授给许多Studen。
数据库包括StudentCourse连接表(中间表),其中包含两个表(Studentt表和Course表)的主键。Entity Framework通过在CSDL和可视化设计器中没有连接表的实体集(DbSet属性)来表示多对多关系。相反,它通过映射进行管理。
正如您在上图中看到的,Student实体包括集合导航属性Courses,而Course实体包括集合导航属性Students,以表示它们之间的多对多关系。
下面的代码片段显示了Student和Course实体类。
public partial class Student
{
public Student()
{
this.Courses = new HashSet<Course>();
}
public int StudentID { get; set; }
public string StudentName { get; set; }
public Nullable<int> StandardId { get; set; }
public byte[] RowVersion { get; set; }
public virtual ICollection<Course> Courses { get; set; } //一个学生可以学习多门课程
}
public partial class Course
{
public Course()
{
this.Students = new HashSet<Student>();
}
public int CourseId { get; set; }
public string CourseName { get; set; }
public System.Data.Entity.Spatial.DbGeography Location { get; set; }
public virtual ICollection<Student> Students { get; set; } //一门课程可以被多个学生学习
}
多对多的关联关系情况下,在两个实体中都添加 对对方的 集合引用导航属性。中间表由Entity Framework来自动生成。
注意:Entity framework仅在连接表(在本例中为StudentCourse)不包括两个表中pk(主键)以外的任何列时支持多对多关系。如果连接表包含额外的列,比如DateCreated,那么EDM也会为中间表创建一个实体,您将不得不手动管理多对多实体的CRUD操作。
在XML视图中打开EDM。您可以看到SSDL(存储模式)有StudentCourse实体集,但是CSDL没有。相反,它被映射到Student和Course实体的导航属性中。MSL (C-S Mapping)将学生和课程之间的映射放到节中的StudentCourse表中。
因此,在EDM中通过C-S映射来管理多对多关系。所以,当你在Course中添加一个Student或在Student中添加一个Course并保存它时,它会在StudentCourse表中插入添加的Student和Course的PK。因此,这种映射不仅可以方便地直接在两个实体之间进行关联,而且还可以跨这些连接管理查询、插入和更新。
参考
https://www.entityframeworktutorial.net/
https://msdn.microsoft.com/