原文链接:https://www.entityframeworktutorial.net/code-first/configure-one-to-many-relationship-in-code-first.aspx

EF 6 Code-First系列文章目录:

这里我们将学习如何在两个实体(领域类)之间配置一对多的关系。
我们使用Student和Grade两个实体配置一对多的关系,一个Grade中可以有很多的Students。

public class Student
{
public int StudentId { get; set; }
public string StudentName { get; set; }
} public class Grade
{
public int GradeId { get; set; }
public string GradeName { get; set; }
public string Section { get; set; }
}

在上面两个实体实现一对多关系之后,数据库中就会生成下面两个表:

一对多的关系,可以通过下面的方式进行配置:

  1. 通过默认的约定
  2. 使用Fluent API进行配置
通过默认约定配置一对多的关系

在EF中有某些约定,只要实体遵循这些约定,EF就会为我们在数据库自动生成一对多的关系数据表。你不用进行任何其他的配置。
我们来看看一对多关系的所有的约定情况吧:

约定1:

我们想要在Student实体和Grade实体之间建立一对多的关系,并且很多学生关联到一个Grade。这就意味着,每一个Student实体指向一个Grade。这种情况可以通过在Student类中包含一个Grade类型的导航属性做到,例如:

public class Student
{
public int Id { get; set; }
public string Name { get; set; }
public Grade Grade { get; set; }
} public class Grade
{
public int GradeId { get; set; }
public string GradeName { get; set; }
public string Section { get; set; }
}

在上面的例子中,Student类包含了一个Grade类型的导航属性,这样就会在Students和Grades表之间生成一对多关系,并且生成外键Grade_GradeId:

请注意:因为应用类型的属性是可空的,所以在Students表中创建的外键列Grade_GradeId是可空的。你可以使用Fluent API配置不为空的外键列。

约定2:

另外一个约定就是,在主体实体中包含一个集合类型的导航属性,例如:

public class Student
{
public int StudentId { get; set; }
public string StudentName { get; set; }
} public class Grade
{
public int GradeId { get; set; }
public string GradeName { get; set; }
public string Section { get; set; } public ICollection<Student> Students { get; set; }
}

在上面例子中Grade实体中包含一个集合类型ICollection的导航属性Students.所以这种也会在Students和Grades表之间生成一对多的关系。生成的数据库结构和约定1中一样。

约定3:

在两个实体中,都包含导航属性:

public class Student
{
public int Id { get; set; }
public string Name { get; set; }
public Grade Grade { get; set; }
} public class Grade
{
public int GradeID { get; set; }
public string GradeName { get; set; }
public string Section { get; set; } public ICollection<Student> Student { get; set; }
}

在上面的代码中,Student实体包含一个Grade类型的导航属性,同样,Grade实体包含一个集合类型ICollection的属性.结果也是在两个表之间生成一对多的关系。生成的数据库结果和约定1,约定2中一样。

约定4:

在两个实体中,完整的定义关系,也会根据约定生成一对多的关系表:

public class Student
{
public int Id { get; set; }
public string Name { get; set; } public int GradeId { get; set; }
public Grade Grade { get; set; }
} public class Grade
{ public int GradeId { get; set; }
public string GradeName { get; set; } public ICollection<Student> Student { get; set; }
}

在上面的例子中,Student实体中,包含一个外键属性GradeId,还有一个Grade类型的导航属性。这样就会生成一对多的关系表。并且Student表中生成的外键GradeId是不可空的:

enter description here

如果GradeId是可空的int类型,那么就会生成可空的外键:

public class Student
{
public int Id { get; set; }
public string Name { get; set; } public int? GradeId { get; set; }
public Grade Grade { get; set; }
}

上面的代码将会生成一个可空的外键GradeId,?只是类型Nullable的简写。

使用Fluent API配置一对多的关系

通常情况下,在EF中你不用配置一对多的关系,因为默认的约定,已经帮我们配置好了。然而你可以使用Fluent API来配置一对多的关系,比默认生成的表更好维护一点。

看看下面的Student和Grade实体:

public class Student
{
public int Id { get; set; }
public string Name { get; set; } public int CurrentGradeId { get; set; }
public Grade CurrentGrade { get; set; }
} public class Grade
{
public int GradeId { get; set; }
public string GradeName { get; set; }
public string Section { get; set; } public ICollection<Student> Students { get; set; }
}

你可以使用Fluent API,重写上下文类中的OnModelCreating方法,来给上面的代码配置一对多的关系:

public class SchoolContext : DbContext
{
public DbSet<Student> Students { get; set; }
public DbSet<Grade> Grades { get; set; } protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
// configures one-to-many relationship
modelBuilder.Entity<Student>()
.HasRequired<Grade>(s => s.CurrentGrade)
.WithMany(g => g.Students)
.HasForeignKey<int>(s => s.CurrentGradeId);
}
}

我们来一步步理解上面的代码:

  • 首先从一个实体类开始配置,所以modelBuilder.Entity()就是从Student实体开始配置。
  • 然后,.HasRequired(s => s.CurrentGrade)指定Student实体,必须要有CurrentGrade属性,这就会在数据库中生成一个不为空的外键。
  • 现在,现在就是配置关系的另外一边,也就是Grade实体。
  • .WithMany(g => g.Students)指定Grade实体包含很多Student实体,这里可以通过ICollcetion类型的属性推断出来。
  • 然后,如果Student实体,不遵循外键的约定【ID property convention】,我们就可以通过HasForeignKey方法指定外键的名称。
  • HasForeignKey(s => s.CurrentGradeId),指定了Student实体中的外键属性。

还有另外一种方式配置一对多关系,就是从Grade实体开始配置,而不是Student实体。下面的代码,生成的数据库和上面的代码生成的是一样的:

modelBuilder.Entity<Grade>()
.HasMany<Student>(g => g.Students)
.WithRequired(s => s.CurrentGrade)
.HasForeignKey<int>(s => s.CurrentGradeId);

代码生成的数据库结构如下:

使用Fluent API配置不为空的外键列

在约定1中,我们看到生成的一对多关系中,外键是可空的,为了生成不为空的外键列,我们可以这样,使用HasRequired方法:

modelBuilder.Entity<Student>()
.HasRequired<Grade>(s => s.CurrentGrade)
.WithMany(g => g.Students);
使用Fluent API配置级联删除

级联删除意味着:当父行被删除之后,自动删除相关的子行。例如:如果Grade被删除了,那么所有在这个Grade中的Students应该同样被自动删除。下面的代码,使用WillCascadeOnDelete方法配置级联删除:

modelBuilder.Entity<Grade>()
.HasMany<Student>(g => g.Students)
.WithRequired(s => s.CurrentGrade)
.WillCascadeOnDelete();

好了,一对多的关系就介绍到这里,下面一节讲解多对多关系。

12.翻译系列:EF 6 中配置一对多的关系【EF 6 Code-First系列】的更多相关文章

  1. 11.翻译系列:在EF 6中配置一对零或者一对一的关系【EF 6 Code-First系列】

    原文链接:https://www.entityframeworktutorial.net/code-first/configure-one-to-one-relationship-in-code-fi ...

  2. 8.翻译系列: EF 6中配置领域类(EF 6 Code-First 系列)

    原文地址:http://www.entityframeworktutorial.net/code-first/configure-classes-in-code-first.aspx EF 6 Cod ...

  3. 20.1翻译系列:EF 6中自动数据迁移技术【EF 6 Code-First系列】

    原文链接:https://www.entityframeworktutorial.net/code-first/automated-migration-in-code-first.aspx EF 6 ...

  4. 20.翻译系列:Code-First中的数据库迁移技术【EF 6 Code-First系列】

    原文链接:https://www.entityframeworktutorial.net/code-first/migration-in-code-first.aspx EF 6 Code-First ...

  5. 19.翻译系列:EF 6中定义自定义的约定【EF 6 Code-First约定】

    原文链接:https://www.entityframeworktutorial.net/entityframework6/custom-conventions-codefirst.aspx EF 6 ...

  6. 9.翻译系列:EF 6以及EF Core中的数据注解特性(EF 6 Code-First系列)

    原文地址:http://www.entityframeworktutorial.net/code-first/dataannotation-in-code-first.aspx EF 6 Code-F ...

  7. css3笔记系列-3.css中的各种选择器详解,不看后悔系列

    点击上方蓝色字体,关注我 最详细的css3选择器解析 ​ 选择器是什么? 比较官方的解释:在 CSS 中,选择器是一种模式,用于选择需要添加样式的元素. 最常见的 CSS 选择器是元素选择器.换句话说 ...

  8. CentOS7系列--5.3CentOS7中配置和管理Kubernetes

    CentOS7配置和管理Kubernetes Kubernetes(k8s)是自动化容器操作的开源平台,这些操作包括部署,调度和节点集群间扩展.如果你曾经用过Docker容器技术部署容器,那么可以将D ...

  9. CentOS7系列--5.2CentOS7中配置和管理Docker

    CentOS7配置和管理Docker Docker是操作系统级别的虚拟化工具,它能自动化布署在容器中的应用 1. 安装Docker 1.1. 安装Docker相关软件 [root@server1 ~] ...

随机推荐

  1. 决策树分类算法及python代码实现案例

    决策树分类算法 1.概述 决策树(decision tree)——是一种被广泛使用的分类算法. 相比贝叶斯算法,决策树的优势在于构造过程不需要任何领域知识或参数设置 在实际应用中,对于探测式的知识发现 ...

  2. class path resource [spring/applicationContext.xml] cannot be opened because it does not exist

    1.查看路径有没有写错 2.编辑器认为你的文件不是 source folders(原文件),需要你手动将文件改过来

  3. 记录一个mysql的case when用法

    SELECT wle.*, CASE WHEN '2017-08-10 14:00:00' > wle.et THEN '回看' WHEN wle.st >= '2017-08-10 14 ...

  4. linux centOS服务器部署ssh,免密码登陆linux

    登陆centos,切换用户,切换到你要免密码登陆的用户,进入到家目录 2 创建钥匙, [xun@jzlinux ~]$ ssh-keygen -t rsa Generating public/priv ...

  5. SpringMvc 文件下载 详解

    最近SSM 需要用到文件下载,以前没用过,在百度上找了好久发现没有一篇博客,对于此段代码进行详细讲解, 这里是本人的个人总结,跟大家分享一下!!!不谢 /** * 文件下载 * ResponseEnt ...

  6. 探秘Tomcat(一)

    前言:有的时候自己不知道自己是井底之蛙,这并没有什么可怕的,因为你只要蜷缩在方寸之间的井里,无数次的生活轨迹无非最终归结还是一个圆形:但是可怕的是有一天你不得不从井里跳出来生活,需要重新审视井以外的生 ...

  7. Python学习——Python线程

    一.线程创建 #方法一:将要执行的方法作为参数传给Thread的构造方法 import threading import time def show(arg): time.sleep(2) print ...

  8. android studio的汉化 教程 及解析

    android studio的汉化 教程 及解析 作者:韩梦飞沙 Author:han_meng_fei_sha 邮箱:313134555@qq.com E-mail: 313134555 @qq.c ...

  9. BZOJ.4727.[POI2017]Turysta(哈密顿路径/回路 竞赛图)

    题目链接 \(Description\) 给出一个n个点的有向图,任意两个点之间有且仅一条有向边.对于每个点v,求出从v出发的一条经过点数最多,且没有重复经过同一个点一次以上的简单路径. n<= ...

  10. AGC 019F.Yes or No(思路 组合)

    题目链接 \(Description\) 一共有\(n+m\)道判断题,其中有\(n\)个答案为"YES",\(m\)个为"NO".现在以随机顺序给你这\(n+ ...