Entity Framework - 理清关系 - 基于外键关联的单向一对一关系
注:本文针对的是 Entity Framework Code First 场景。
之前写过三篇文章试图理清Entity Framework中的一对一关系(单相思(单向一对一), 两情相悦(双向一对一), 两情相悦-续),但当时理得不够清,新的一年重新理一理。
当时“一对一”的实体关系,对应的数据库关系是外键关联(实际上是一种“一对多”关系,所以映射时用了WithMany)。而数据库中的“一对一”关系是共享主键(这是我个人的理解,不妥之处,欢迎指出),下篇文章将要理的就是这个关系。
由于双向“一对一”关系很少用到,而且不推荐使用,为了更清楚地理解,我们这里只谈单向一对一关系,也就是“基于外键关联的单向一对一关系(One-to-one Unidirectional relationships)”,对应的之前的文章是单相思(单向一对一)。
1. 类图

2. 类的定义

public class BlogSite { public int BlogID { get; set; } public string BlogApp { get; set; } public bool IsActive { get; set; } public Guid UserID { get; set; } public virtual BlogUser BlogUser { get; set; } }


public class BlogUser { public Guid UserID { get; set; } public string Author { get; set; } public int BlogID { get; set; } }

3. 数据库结构

4. Enitity Framework映射关系定义

protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Entity<BlogSite>() .HasRequired(b => b.BlogUser) .WithMany(); }

怎么理解这里的HasRequired与WithMany呢?
我的理解是:HasRequired是针对BlogSite与BlogUser的关系,WithMany是针对BlogUser与BlogSite的关系。.HasRequired(b => b.BlogUser).WithMany()表示BlogSite与BlogUser存在Required关联关系(One-To-One, 每一个BlogSite都有一个对应的BlogUser),而这个关联对BlogUser来说是One-To-Many(一个BlogUser可以有多个BlogSite)。
你也许会疑惑?明明是单向一对一的实体关系,这里怎么弄出个一对多的关系?
如果有这样的疑惑,属正常现象,我从去年7月份写那篇文章开始疑惑,一直疑惑到现在,写篇文章时才有点搞明白。
注意,“单向一对一”是什么?是实体关系;Entity Framework是什么?是O/RM,是用来映射实体关系与数据库关系;还少了什么?数据库关系。
从上面的图中的数据库结构可以看出,BlogSite与BlogUser之间是外键关联关系,下面的图可以更清楚地看出这一点。

这个外键关联表示的就是BlogUser与BlogSite之间是一对多的数据库关系。
总结一下:
实体关系 —— BlogSite与BlogUser之间的单向一对一
数据库关系 —— BlogUser与BlogSite之间的一对多
是不是这样呢?Entity Framework是不是也是这样认为的呢?我们来验证一下。
怎么知道Entity Framework的想法呢?
通过EDM。
可这里是Code First?
不管什么First,都有EDM,因为这是Entity Framework的地图,没有它,Entity Framework就会晕头转向。Code First的EDM是在EF运行时生成的,不是没有地图,只是在Entity Framework的心中,我们看不到而已。
怎么让Entity Framework说出心里话呢?
从Morteza Manavi大师那学到一招,代码如下:

using (var context = new Context()) { XmlWriterSettings settings = new XmlWriterSettings(); settings.Indent = true; using (XmlWriter writer = XmlWriter.Create(@"Model.edmx", settings)) { EdmxWriter.WriteEdmx(context, writer); } }

通过上面的代码,你就可以拿到EF心中的地图 —— edmx文件。请看地图:

果然,EF心中的地图就是BlogUser与BlogSite的一对多关系。地图的作用是什么?是让EF通过地图在数据库找到对应的数据。地图是如何产生的?是我们通过FluentAPI告诉Entity Framework:.HasRequired(b => b.BlogUser).WithMany()。
我们再来剖析一下.HasRequired(b => b.BlogUser).WithMany()。
之前,我一直被困扰,是因为总是把这里的定义当作实体的关系的定义。错!这里虽然用的是实体进行定义,但定义的是实体与数据库中的数据之间的映射关系(这本来就是常识,竟然被忽略了),更多的是告诉EF这些实体在数据库中的数据关系。EF最终是根据这个定义生成相应的SQL。
那我们从生成查询SQL的角度来理解一下:
.HasRequired(b => b.BlogUser)告诉EF,这是一个INNER JOIN查询(BlogSite INNER JOIN BlogUser);但INNER JOIN还需要条件,WithMany()告诉EF这是一个外键关联,EF据此进行推断,从BlogUser中找到主键UserID,并检查BlogSite中是否存在名为UserID的属性,如果存在,就以此为外键进行查询。而我们的BlogSite中有UserID,于是生成下面的SQL:

SELECT [Extent1].[BlogID] AS [BlogID], [Extent1].[BlogApp] AS [BlogApp], [Extent1].[IsActive] AS [IsActive], [Extent1].[UserID] AS [UserID], [Extent2].[UserID] AS [UserID1], [Extent2].[Author] AS [Author] FROM [dbo].[BlogSite] AS [Extent1] INNER JOIN [dbo].[BlogUser] AS [Extent2] ON [Extent1].[UserID] = [Extent2].[UserID] WHERE 1 = [Extent1].[IsActive]

小结
理清“基于外键关联的单向一对一关系”,关键在于对modelBuilder.Entity<A>().HasRequired(A => A.B).WithMany()的理解。
我再来理解一次:
.HasRequired(A => A.B) 表示:1)实体A与实体B是一对一关系,实体A有一个导航属性A.B;2)在数据库中表A与表B存在一对一关联(INNER JOIN)。
.WithMany() 表示:1) 实体B与实体A可以没有关系,也可以是一对多关系;2)在数据库中表A与表B存在外键关联。
上面全是我的个人理解,真正理清Entity Framework中的关系需要大家的力量,我只是抛个砖。
除了“基于外键关联的单向一对一关系”,还有“基于共享主键的单向一对一关系”,这也是我们开发中经常碰到的一种关系,比如博客文章(BlogPost)与文章内容(PostBody),新闻(NewsItem)与新闻内容(NewsBody)。下一篇文章将会理理这个关系。
Entity Framework - 理清关系 - 基于外键关联的单向一对一关系的更多相关文章
- Entity Framework - 基于外键关联的单向一对一关系
代码的世界,原以为世界关系很简单,确道是关系无处不在.NET世界里ORM框架中EntityFramework作为其中翘楚,大大解放了搬砖工作的重复工作,着实提高了不少生产力,而也碰到过不少问题!比如关 ...
- Entity Framework Code First主外键关系映射约定
本篇随笔目录: 1.外键列名默认约定 2.一对多关系 3.一对一关系 4.多对多关系 5.一对多自反关系 6.多对多自反关系 在关系数据库中,不同表之间往往不是全部都单独存在,而是相互存在关联的.两个 ...
- Entity Framework 实体间的外键关系
EF 默认是开户级联删除的,这此规则将会删除非空外键和多对多的关系,如果 在数据库上下文中的实体模型类 存在着 级联引用和多重删除路径,那么EF就抛出 级联引用和多重删除路径的异常. Introduc ...
- Hibernate,关系映射的多对一单向关联、多对一双向关联、一对一主键关联、一对一外键关联、多对多关系关联
2018-11-10 22:27:02开始写 下图内容ORM.Hibernate介绍.hibername.cfg.xml结构: 下图内容hibernate映射文件结构介绍 下图内容hibernate ...
- 《Entity Framework 6 Recipes》中文翻译系列 (29) ------ 第五章 加载实体和导航属性之过滤预先加载的实体集合和修改外键关联
翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 5-13 过滤预先加载的实体集合 问题 你想过滤预先加载的实体集合,另外,你想使用 ...
- Hibernate 再接触 关系映射 一对一单向外键关联
对象之间的关系 数据库之间的关系只有外键 注意说关系的时候一定要反面也要说通 CRUD 数据库之间设计 主键关联 单向的外键关联 中间表 一对一单向外键关联 Husband.java package ...
- hibernate笔记--基于外键的单(双)向的一对一映射关系
假设我们有两张表,人员信息表Person,和身份信息表IdCard,我们知道每个人只有一个身份证号,所以这里的Person和IdCard表是一一对应的,也就是一对一的映射关系,基于外键的单向一对一映射 ...
- 《Entity Framework 6 Recipes》中文翻译系列 (37) ------ 第六章 继承与建模高级应用之独立关联与外键关联
翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 6-13 在基类中应用条件 问题 你想从一个已存在的模型中的实体派生一个新的实体, ...
- Entity FrameWork对有外键关联的数据表的添加操作
前天做了一个MVC Entity FrameWork项目,遇到有外键关联的数据编辑问题.当你编辑的时候,按照正常的逻辑,把每个字段的数据都对号入座了,然后点击保存按钮,本以为会顺理成章的编辑数据,但是 ...
随机推荐
- python介绍(转载)
Python简介 python的创始人为吉多·范罗苏姆(Guido van Rossum).1989年的圣诞节期间,吉多·范罗苏姆为了在阿姆斯特丹打发时间,决心开发一个新的脚本解释程序,作为ABC语言 ...
- Blend操作入门: 别站在门外偷看,快进来吧!(转)
来源:http://www.cnblogs.com/hielvis/archive/2010/10/21/1857415.html 有的人认为,Blend主要是用来修改一下颜色,调整一下布局之类的,大 ...
- jQuery细节总结
1.mouseover和mouseenter 区别 mouseenter指鼠标进入元素时触发,鼠标在元素子元素上不触发. mouseover指鼠标进入元素时触发,在元素进入子元素会触发. 在此引用一个 ...
- c 函数调用产生的汇编指令和数据在内存情况(1)
一直对函数调用的具体汇编指令和各种变量在内存的具体分配,一知半解.各种资料都很详细,但是不实践,不亲自查看下内存总不能笃定.那就自己做下. 两个目的: 一,函数和函数调用编译后的汇编指令基本样貌 二, ...
- alloc && afree
#define ALLOCSIZE 10000 static char allocbuf[ALLOCSIZE]; static char *allocp = allocbuf; char *alloc ...
- [转发] 理解 oauth 2.0
原文: http://www.ruanyifeng.com/blog/2014/05/oauth_2_0.html oauth 的各种编程语言实现: http://oauth.net/2/ 理解OAu ...
- bootstrap学习笔记<十一>(导航条)
基础导航条.样式:class="navbar navbar-default",属性:role="navigation" <div class=" ...
- 转:最小区间:k个有序的数组,找到最小区间使k个数组中每个数组至少有一个数在区间中
转:http://www.itmian4.com/thread-6504-1-1.html 最小区间原题 k个有序的数组,找到最小的区间范围使得这k个数组中,每个数组至少有一个数字在这个区间范围内.比 ...
- linux mount命令的用法详细解析
挂接命令(mount)首先,介绍一下挂接(mount)命令的使用方法,mount命令参数非常多,这里主要讲一下今天我们要用到的.命令格式:mount [-t vfstype] [-o options] ...
- Java Performance - 优化和分析Garbage Collection/垃圾收集
随着硬件的不断提升,Java Heap 越来越大,合理的垃圾收集调优变得愈发重要.下面介绍一些最佳实践: 注意: 下面不涉及 IBM AIX Java. 同时不介绍原理,仅仅是建议以及初始配置/最佳实 ...