通过 Entiy Framework实践系列 文章,理了理 Entity Framework 的实体关系。

为什么要写文章来理清这些关系?“血”的教训啊,刚开始使用 Entity Framework 的时候,由于没有静下心来认真理清关系,走了一些"痛不欲生"的弯路。而我们目前开发的项目都在使用 Entity Framework,为了避免其他人再经历"痛不欲生"的弯路。于是下定决心边“理清关系”边“写博客”。而写博客可以逼着自己把问题完整地解决,避免半 途而废。当写出这些文章,自己不知不觉对问题有了更深的理解。

温故而知新,通过这篇总结将自己对EF实体关系的理解回锅热一热,也许会有新的收获;感情也一样,当感情冷下来的时候,别忘了回锅热一热。

1. 一对一关系(one-to-one)

a) 单向一对一(文章链接

类图:

数据库表结构:

Entity Framework中实体关系的定义:

modelBuilder.Entity<BlogSite>()
.HasRequired(b => b.BlogUser)
.WithMany()
.HasForeignKey(b => b.UserID);

b) 双向一对一(文章链接

类图:

数据库表结构:

Entity Framework中实体关系的定义:

modelBuilder.Entity<BlogSite>()
.HasRequired(b => b.BlogUser)
.WithMany()
.HasForeignKey(b => b.UserID); modelBuilder.Entity<BlogUser>()
.HasRequired(u => u.BlogSite)
.WithMany()
.HasForeignKey(u => u.BlogID);


2. 一对多关系(one-to-many,文章链接

类图:

数据库表结构:

Entity Framework中实体关系的定义:

modelBuilder.Entity<BlogSite>()
.HasMany(b => b.BlogPosts)
.WithRequired(p => p.BlogSite);


3. 多对多关系(many-to-many,文章链接

类图:

数据库表结构:

Entity Framework中实体关系的定义:

modelBuilder.Entity<BlogPost>()
.HasMany(b => b.Categories)
.WithMany(c => c.BlogPosts)
.Map
(
m =>
{
m.MapLeftKey("BlogPostID");
m.MapRightKey("CategoryID");
m.ToTable("BlogPost_Category");
}
);
 
 
-------------------------------

HasMany() = (1..*), HasOptional() = (1..0,1), HasRequired() = (1..1)

-------------------------------

在演示Fluent API如何配置Person类和PersonPhoto的一对一关系之前,先系统的学习下EF里实体关系配置的方法。EF里的实体关系配置分为Has和With系列的方法:Optional 可选的、Required 必须的、Many 多个。举例:

A.HasRequired(a => a.B).WithOptional(b => b.A);

这里的a=>a.B是lambda表示写法,就是找到A类里的导航属性B。命名a不固定,可以随意,q=>q.B也是可以的。但是B是A类的属性,故习惯用小写a。

Has方法:

  1. HasOptional:前者包含后者一个实例或者为null
  2. HasRequired:前者(A)包含后者(B)一个不为null的实例
  3. HasMany:前者包含后者实例的集合

With方法:

  1. WithOptional:后者(B)可以包含前者(A)一个实例或者null
  2. WithRequired:后者包含前者一个不为null的实例
  3. WithMany:后者包含前者实例的集合

摘自这里 这是较为好的理解方式。上面一句配置意思就是A类包含B类一个不为null的实例,B类包含A类一个实例,也可以不包含。最标准的一对一配置。ok,现在试着写下上面Person类和PersonPhoto类的一对一的关系如何配置:

this.HasRequired(p => p.PhotoOf).WithOptional(p => p.Photo);

再跑下程序,数据库就生成了,是一对一的关系。Person表可以没有对应的PersonPhoto表数据,但是PersonPhoto表每一条数据都必须对应一条Person表数据。意思就是人可以没有照片,但是有的照片必须属于某个人。关系配置是这样的效果,其实可以随便改,也可以配置成每个人都必须有对应的照片。把上面的WithOptional改成WithRequired,对应到数据库里就是null变成了not null。

数据库里可以可视化的设置不级联删除,Fluent API配置此外键关系时可以设置不级联删除:

this.HasMany(d => d.Lodgings).WithRequired(l => l.Destination)
.Map(l => l.MapKey("DestinationId")) //一对多并指定外键名
.WillCascadeOnDelete(false); // 关闭级联删除

再跑下程序,去看下数据库本外键自然就没了级联删除。

园友郭明锋提供了一个很好的建议:考虑到EF中的级联删除并不常用,所以可以在全局里关掉所有主外键关系的级联删除,如果需要可以打开某个主外键的级联删除。

@郭明锋:好文章,很久没有看到这么好的EF文章了,推荐
EF默认开启级联删除,确实是挺操蛋的设置,所以我的做法是在上下文的OnModelCreating方法中
modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
移除这个默认约定,再在需要开启级联删除的FluentAPI关系映射中用. WillCascadeOnDelete(true) 单独开启

[转]Entity Framework 的实体关系的更多相关文章

  1. Entity Framework管理实体关系(二):管理一对二关系

    在上一篇文章中,简单的介绍了使用Fluent API如何管理一对一的实体关系,在这篇文章中,接着介绍Fluent API如何管理一对多的实体关系. 要在数据库中配置一对多关系,我们可以依赖EF约定,还 ...

  2. Entity Framework管理实体关系(一):管理一对一关系

    我们现在已经知道如何使用Code First来定义简单的领域类,并且如何使用DbContext类来执行数据库操作.现在我们来看下数据库理论中的多样性关系,我们会使用Code First来实现下面的几种 ...

  3. Entity Framework Code First关系映射约定

    本篇随笔目录: 1.外键列名默认约定 2.一对多关系 3.一对一关系 4.多对多关系 5.一对多自反关系 6.多对多自反关系 在关系数据库中,不同表之间往往不是全部都单独存在,而是相互存在关联的.两个 ...

  4. EF(Entity Framework)多对多关系下用LINQ实现"NOT IN"查询

    这是今天在实际开发中遇到的一个问题,需求是查询未分类的博文列表(未加入任何分类的博文),之前是通过存储过程实现的,今天用EF实现了,在这篇博文中记录一下. 博文的实体类BlogPost是这样定义的: ...

  5. Entity Framework(实体框架 EF)

    什么是Entity Framework呢(下面简称EF)? EF(实体框架)是ADO.NET中的一组支持开发面向数据的软件应用程序的技术,是微软的一个ORM框架.ORM(对象关系映射框架):指的是面向 ...

  6. Entity Framework Code First关系映射约定【l转发】

    本篇随笔目录: 1.外键列名默认约定 2.一对多关系 3.一对一关系 4.多对多关系 5.一对多自反关系 6.多对多自反关系 在关系数据库中,不同表之间往往不是全部都单独存在,而是相互存在关联的.两个 ...

  7. Entity Framework一对多关系添加数据的两种方式

    当使用Entity Framework添加一对多关系数据的时候,通常先添加一的数据,然后再添加多的数据.类似这样: //添加一的数据 var category = new Category{Name= ...

  8. Entity Framework关联实体的三种加载方法

    推荐文章 EF性能之关联加载 总结很好 一:介绍三种加载方式 Entity Framework作为一个优秀的ORM框架,它使得操作数据库就像操作内存中的数据一样,但是这种抽象是有性能代价的,故鱼和熊掌 ...

  9. [CareerCup] 15.6 Entity Relationship Diagram 实体关系图

    15.6 Draw an entity-relationship diagram for a database with companies, people, and professionals (p ...

随机推荐

  1. (转)Android 创建与解析XML—— Dom4j方式 .

    转:http://blog.csdn.net/ithomer/article/details/7521605 1.Dom4j概述 dom4j is an easy to use, open sourc ...

  2. PAT_A1053#Path of Equal Weight

    Source: PAT A1053 Path of Equal Weight (30 分) Description: Given a non-empty tree with root R, and w ...

  3. static 关键字的使用及说明

    static 关键字主要有以下几种使用场景: 修饰类的成员变量. 修饰类的成员方法. 修饰类的代码块. 修饰内部类. 1. static 修饰类的成员变量时,被称为静态成员变量.引用 static 修 ...

  4. 高手总结CSS书写技巧

    这个时候我们就需要针对不同的浏览器去写不同的CSS,让它能够同时兼容不同的浏览器,能在不同的浏览器中也能得到我们想要的页面效果.这个针对不同的浏览器写不同的CSS code的过程,就叫CSS hack ...

  5. licecap图片区域问题

    之前一直好用的licecap最近突然没法用了,结果发现是屏幕分辨率的文本大小的问题,因为选了特大的.发现制作成的gif图片的区域有问题.后来改回中等的,就可以了.

  6. C++数据类型之字符串类型&布尔类型&数据的输入

    字符串型 **作用**:用于表示一串字符 **两种风格** 1. **C风格字符串**: char 变量名 [ ]  =  "字符串值" 2.**C++风格字符串**:  stri ...

  7. 16-Ubuntu-文件和目录命令-切换目录-cd

    cd(change directory),其功能为更改当前的工作目录. 注意:Linux所有的目录和文件名都是大小写敏感的. 命令 含义 cd     切换到当前用户的主目录(/home/用户目录) ...

  8. [AH2017/HNOI2017]单旋

    题目 \(\rm splay\)水平太差,于是得手玩一下才能发现规律 首先插入一个数,其肯定会成为其前驱的右儿子或者是后继的左儿子,进一步手玩发现前驱的右儿子或者是后继的左儿子一定只有一个是空的,我们 ...

  9. jQuery post使用变量作参数名

    jQuery Query Post使用方法: $.post("test.php", { name: "John", time: "2pm" ...

  10. python接口自动化(接口基础)

    一.什么是接口? 前端负责展示和收集数据 后端负责处理数据,返回对应的结果 接口是前端与后端之间的桥梁,传递数据的通道 二.