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 ...
随机推荐
- 【译】使用 ndb 调试 node 应用
原文链接:Debugging Node.js Application Using ndb Google Chrome 实验室发布了一款新的 node debug 工具来提升开发者体验,本文将会全面介绍 ...
- Java架构师最关键三个思维转变方式,框架的合理运用
很久没有写思维的文章,特别是在写完思维的逻辑和思维的框架后,对于理论层面的自己也不太想写,但是对于实际案例层面的写起来又比较花时间,而且案例基本在IT专业领域不是所有人都能看明白. 我们前面写过思维的 ...
- python TypeError: 'int' object is not callable 问题解决
TypeError: 'int' object is not callable 这个错误的原因很简单 看下面的程序: def loss(a,b): return a-b loss = 0 loss = ...
- numpy中pad函数的常用方法
一.参数解释 ndarray = numpy.pad(array, pad_width, mode, **kwargs) array为要填补的数组 pad_width是在各维度的各个方向上想要填补的长 ...
- iOS事件拦截及应用
1.概述 我们知道事件的分发是由Application到Window再到各级View的,所以显然最安全可靠的拦截地方是Application.这里拦截事件后如果不手动往下分发,则进入hit-test ...
- Myeclipse--jBPM4.3插件
http://www.baidupcs.com/file/c7f3b8fc57b056567b37d081b1bcd21e?xcode=3966699596a0e8ec88581bd8407457f9 ...
- Linux命令yum和rpm
yum命令使用 可以简化软件安装命令 yum可以做软件的 1自动安装,安装软件的时候会自动安装需要的依赖 yum install 软件名如安装epel源yum install epel-release ...
- 内核开发知识第二讲,编写Kerner 程序中注意的问题.
一丶函数多线程的安全问题 什么是函数多线程安全. 简单来说就是 ,一个函数在调用过程中.还没有返回的时候.再次被其他线程调用了.但是函数执行的结果是可靠的.就可以了说这个函数是安全的. 比如我们在用户 ...
- 【详解】WebSocket相关知识整理
前言 记得大概半年前就产生了疑惑,即后台如何主动向前端推送数据.问了下专业老师,知道了原来有一个叫WebSocket的技术可以用于推送数据.于是,当时我就找了个教程,用的是Spring WebSock ...
- utf-8的中文,一个字符占几个字节
https://blog.csdn.net/kindsuper_liu/article/details/80202150 英文字母和中文汉字在不同字符集编码下的字节数英文字母:·字节数 : 1;编码: ...