EntityFramework Code-First 简易教程(八)-------一对一
配置一对一(One-to-One)关系:
两个实体中,如果一个实体的一个实例与另一个实体相关,则我们就叫做一对一关系
查看如下代码:
public class Student
{
public Student() { } public int StudentId { get; set; }
public string StudentName { get; set; } public virtual StudentAddress Address { get; set; } } public class StudentAddress
{
public int StudentAddressId { get; set; } public string Address1 { get; set; }
public string Address2 { get; set; }
public string City { get; set; }
public int Zipcode { get; set; }
public string State { get; set; }
public string Country { get; set; } public virtual Student Student { get; set; }
}
这里,Student类只能拥有零个或最多一个StudentAddress类,所以符合一对一关系
在SQL Server数据库中,一对一关系发生在当一张表的主键是另一张表的主键或外键时,所以如上代码中,我们要配置StudentId为主键,StudentAddressId既为主键也为外键。
1.使用DataAnnotations配置一对零或一对一关系:
Student类会根据Code-First默认约定将StudentId属性配置为主键,所以这里我们就不用额外的配置它了。
StudentAddress类中,我们需要配置StudentAddressId既为主键又为外键,同样的,Code-First默认约定会将StudentAddressId配置为主键,所以这里我们仅仅需要使用[ForeignKey("Student")]特性将StudentAddressId属性配置为外键即可。
代码如下:
public class Student
{
public Student() { } public int StudentId { get; set; }
public string StudentName { get; set; } public virtual StudentAddress Address { get; set; } } public class StudentAddress
{
[ForeignKey("Student")]
public int StudentAddressId { get; set; } public string Address1 { get; set; }
public string Address2 { get; set; }
public string City { get; set; }
public int Zipcode { get; set; }
public string State { get; set; }
public string Country { get; set; } public virtual Student Student { get; set; }
}
这样,Student类和StudentAddress类就配置好了一对一关系。
如果StudentAddressId名称改变了,比如下面代码,改成了StudentId,默认就不会创建主键了,需要手动添加上[Key]特性:
public class Student
{
public Student() { } public int StudentId { get; set; }
public string StudentName { get; set; } public virtual StudentAddress Address { get; set; } } public class StudentAddress
{
[Key, ForeignKey("Student")]
public int StudentId { get; set; } public string Address1 { get; set; }
public string Address2 { get; set; }
public string City { get; set; }
public int Zipcode { get; set; }
public string State { get; set; }
public string Country { get; set; } public virtual Student Student { get; set; }
}
这样,StudentAddress类中的StudentId就被配置为既是主键,又是外键。
注意: 虽然Student类中包含StudentAddress类属性,StudentAddress类中也包含Student类属性,但Student类的StudentAddress类属性可以为空,而StudentAddress类的Student类属性不能为空!如果保存一个Student类属性为空的StudentAddress类,会抛出异常。
2.使用Fluent API配置一对零或一对一关系:
下面我们将不使用任何DataAnnotations特性(虽然它们可以一起使用)仅仅使用Fluent API来配置一对一关系。
当Student类的命名和StudentAddress类的命名遵循默认约定的时候:
既然默认约定会自动为Student和StudentAddress创建主键,所以这里我们仅仅需要把StudentAddressId配置为外键
代码如下:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{ // Configure Student & StudentAddress entity
modelBuilder.Entity<Student>()
.HasOptional(s => s.Address) // Mark Address property optional in Student entity
.WithRequired(ad => ad.Student); // mark Student property as required in StudentAddress entity. Cannot save StudentAddress without Student }
上面代码中,Student实体的Address属性使用了HasOptional()方法,即Address属性不是必须的,可为空,又为StudentAddress类的Student属性使用了WithRequired()方法,即Student属性为必填,不能为空,如果存储StudentAddress实体的时候发现Student属性为空,则会抛出异常。
这样配置以后,StudentAddressId就已经是外键了。
当StudentAddress类的命名不遵循默认约定的时候:
如下代码,我们想要StudentAddress类的StudentId属性成为主外键
public class Student
{
public Student() { } public int StudentId { get; set; }
public string StudentName { get; set; } public virtual StudentAddress Address { get; set; } } public class StudentAddress
{
public int StudentId { get; set; } public string Address1 { get; set; }
public string Address2 { get; set; }
public string City { get; set; }
public int Zipcode { get; set; }
public string State { get; set; }
public string Country { get; set; } public virtual Student Student { get; set; }
}
Fluent API配置如下:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
// Configure StudentId as PK for StudentAddress
modelBuilder.Entity<StudentAddress>()
.HasKey(e => e.StudentId); // Configure StudentId as FK for StudentAddress
modelBuilder.Entity<Student>()
.HasOptional(s => s.Address)
.WithRequired(ad => ad.Student); }
3.使用Fluent API配置一对一关系:
说白了,所谓的一对一关系,即是两个实体类中作为主外键的类属性都不能为空。
注意:一对一关系在SQL Server中并不是必须,通常使用一对零或一对一。
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
// Configure StudentId as PK for StudentAddress
modelBuilder.Entity<StudentAddress>()
.HasKey(e => e.StudentId); // Configure StudentId as FK for StudentAddress
modelBuilder.Entity<Student>()
.HasRequired(s => s.Address)
.WithRequiredPrincipal(ad => ad.Student); }
在上面的代码中, modelBuilder.Entity<Student>().HasRequired(s => s.Address)使得Student类的Address属性为必须,WithRequiredPrincipal(ad => ad.Student) 方法使的StudentAddress类的Student属性为必须。
注意:这里主要的实体类是Student,依赖的实体类是StudentAddress。
DataAnnotations and Fluent API都会创建如下的一对零或一对一关系的数据库:
我们可以检查Student表和StudentAddress表之间的关系:
图表关系如下
啊啊啊啊啊,虽然最近忙成狗,但是说好的翻译,一定会坚持下去的!!!
EntityFramework Code-First 简易教程(八)-------一对一的更多相关文章
- WebGL简易教程(八):三维场景交互
目录 1. 概述 2. 实例 2.1. 重绘刷新 2.2. 鼠标事件调整参数 3. 结果 4. 参考 1. 概述 在上一篇教程<WebGL简易教程(七):绘制一个矩形体>中,通过一个绘制矩 ...
- Entity Frame Code First 简易教程
简介 什么是ORM 搭建Entity FrameWork CodeFirst应用 数据库迁移 表属性常见配置 Entity FrameWork 一对多.多对多 一.简介 Entity Framewor ...
- Dart 语言简易教程系列
google Fuchsia系统 及 dart语言简介 在 InteIIiJ IDEA 中搭建 Dart 的开发环境 Dart Linux 开发环境搭建 Dart 语言简易教程(一) Dart 语言简 ...
- WebGL简易教程(九):综合实例:地形的绘制
目录 1. 概述 2. 实例 2.1. TerrainViewer.html 2.2. TerrainViewer.js 3. 结果 4. 参考 1. 概述 在上一篇教程<WebGL简易教程(八 ...
- WebGL简易教程——目录
目录 1. 绪论 2. 目录 3. 资源 1. 绪论 最近研究WebGL,看了<WebGL编程指南>这本书,结合自己的专业知识写的一系列教程.之前在看OpenGL/WebGL的时候总是感觉 ...
- CURL (CommandLine Uniform Resource Locator) 简易教程!
1 http://curl.haxx.se/ http://curl.haxx.se/docs/httpscripting.html curl is an open source command li ...
- CRL快速开发框架系列教程八(使用CRL.Package)
本系列目录 CRL快速开发框架系列教程一(Code First数据表不需再关心) CRL快速开发框架系列教程二(基于Lambda表达式查询) CRL快速开发框架系列教程三(更新数据) CRL快速开发框 ...
- 文件上传利器SWFUpload入门简易教程
凡做过网站开发的都应该知道表单file的确鸡肋. Ajax解决了不刷新页面提交表单,但是却没有解决文件上传不刷新页面,当然也有其它技术让不刷新页面而提交文件,该技术主要是利用隐藏的iFrame, 较A ...
- Ant 简易教程
转载:http://www.cnblogs.com/jingmoxukong/p/4433945.html Ant 简易教程 Apache Ant,是一个将软件编译.测试.部署等步骤联系在一起加以自动 ...
- Intellj IDEA 简易教程
Intellj IDEA 简易教程 目录 JDK 安装测试 IDEA 安装测试 调试 单元测试 重构 Git Android 其他 参考资料 Java开发IDE(Integrated Developm ...
随机推荐
- C#开源项目大全
C#开源项目大全 商业协作和项目管理平台-TeamLab 网络视频会议软件-VMukti 驰骋工作流程引擎-ccflow [免费]正则表达式测试工具-Regex-Tester Windows-Ph ...
- 【Java基本功】一文读懂String及其包装类的实现原理
String作为Java中最常用的引用类型,相对来说基本上都比较熟悉,无论在平时的编码过程中还是在笔试面试中,String都很受到青睐,然而,在使用String过程中,又有较多需要注意的细节之处. S ...
- 模型评估——ROC、KS
无论是利用模型对信用申请人进行违约识别,还是对授信申请人进行逾期识别……在各种各样的统计建模中,永远必不可少的一步是对模型的评价,这样我们就可以根据模型评价指标的取值高低,来决定选取哪个模型.本篇主要 ...
- winform 窗体关闭枚举类
switch (e.CloseReason) { case CloseReason.None: break; case CloseReason.WindowsShutDown: break; case ...
- Linux系列教程(三)——Linux学习技巧
前面我们讲了Linux系统的详细安装教程,大家跟着教程一步一步的操作,应该能完美的完成安装.那么这篇博客跟大家聊聊如何来学习Linux. 1.工欲善其事必先利其器 ①.第一个问题:通过前面在虚拟软件中 ...
- SaltStack数据系统-Pillar详解
1:存储位置 存储在master端,存放需要提供给minion的信息 每个minion只能访问master分配给自己的(应用场景) 2:在centos7 salt 2015.5.10 (Lithium ...
- python实现定时任务
定时任务的实现方式有很多种,如windows服务,借助其他定时器jenkins运行脚本等方式.本文介绍的是python中的一个轻量级模块schedule. 安装 pip命令:pip install s ...
- [转]Angular4 自制分页控件
本文转自:https://blog.csdn.net/Junyuan_123/article/details/79486276 过年后第一波,自制的分页控件,可能功能没有 PrimeNG 那么好,但是 ...
- [PHP] 算法-构建排除当前元素的乘积数组的PHP实现
构建乘积数组给定一个数组A[0,1,...,n-1],请构建一个数组B[0,1,...,n-1],其中B中的元素B[i]=A[0]*A[1]*...*A[i-1]*A[i+1]*...*A[n-1]. ...
- 【协议】4、http状态码
10.4 客户错误 4xx 状态代码4xx类是专门使用在客户看上去错误的情形下的.除非当应答一个HEAD请求时,服务器因该有一个包括错误情形的解释的实体,以及它是否一个临时或者终了的条件.这些状态编码 ...