数据库表之间有一对一  一对多 多对多关系。那同样,CodeFirst也要能分析这些类之间的这些关系。

CodeFirst可以自动通过分析类之间的属性导航属性 从而得出类之间的关系,自动确定外键。


一对多
一对多是最为常见的一种关系,符合怎样的规范会被CodeFirst识别为一对多的关系呢?
    public class Blog
{
public string ID { get; set; }
public string BlogName { get; set; }
public string BlogAuthor { get; set; }
public virtual List <Post> Posts { get; set ; } //导航属性
public virtual List <Article> Articles { get; set; } //导航属性
[ Timestamp]
public byte [] version { get; set; }
} public class Post
{
public string ID { get; set; }
public string PostName { get; set; }
public string Content { get; set; }
public virtual Blog BelongBlog { get; set; } //导航属性
}
public class Article
{
public string ID { get; set; }
public string ArticleName { get; set; }
public string Content { get; set; }
}
CodeFirst发现 Blog中有两个集合导航属性,Post中也有一个Blog类型的引用属性,分析出Blog和 Post以及Article之间都存在一对多的关系。
我们还可以发现 Article中并没有 Blog类型的导航属性,并且 Post和Article生成的主键名称不一样。
其实EF推断两个类之间存在一堆多的关系,只需要 两个类中的其中一个存在指向另一个类的导航属性即可。
并且 外键名称的生成规则是 首先是 导航属性名称+ 下划线_ +ID 如果导航属性不存在 那就是 另一个类的类名+ID
 
存在显示的符合规范的外键
有些时候就是手贱,喜欢手动写上外键,那么属性名称符合什么样的规范会被CodeFirst识别为外键,而不是一般属性呢?(当然前提是已经存在导航属性)
当属性符合 [目标类型的键名],[目标类型名称]+[目标类型键名称],或[导航属性名称]+[目标类型键名称]的形式的时候,会被判定为外键。
 
当两个类之间存在多个关系时会怎样呢?在Post类中,有可能需要跟踪谁创建了它,以及谁编辑了它。那么Post类就需要增加两个导航属性
   public  Person CreatedBy { get; set; }
public Person UpdatedBy { get; set; }
那同样在我们的Person类之中,也需要加上两个属性,一个属性指向这个人创建的所有文章,另一个属性指向之个人更新的所有文章。
 public virtual List<Post> PostsWritten { get; set; }
public virtual List <Post> PostsUpdated { get; set ; }

会发现这时候生成了四个外键,这是因为当类之间存在多个关系的时候,EF是无法准确分辨的,需要我们手动的添加代码来帮助EF分析。要想解决这个问题 就要用另一个数据注释 : InverseProperty 代码赢改成如下
        [InverseProperty( "CreatedBy")]
public virtual List <Post> PostsWritten { get; set ; }
[ InverseProperty("UpdatedBy" )]
public virtual List <Post> PostsUpdated { get; set ; }
要注意 InverseProperty括号内的名称是要与另一个类的相关的导航属性名称相匹配的,否则会报错。
这个时候数据库外键就正确了

多对多
如果两个类之间,各自都有集合导航属性指向对方,那这两个类之间的关键会被识别为多对多关系。
 public class Student
{
public int StudentID { get; set; }
public string Name { get; set; }
public List <Course> Courses { get; set ; }
}
public class Course
{
public int CourseID { get; set; }
public string CourseName { get; set; }
public List <Student> Students { get; set ; }
}
学生可以选择多门课程,每门课也有很多学生,这样的多对对关系,codefirst会自动生成第三张表,表里存放另外两张表的主键作为外键存放。

一对一
在一对一和一对多的关系之后,我们回头再来讲一对一的关系。
如果需要将两个类之间的关系配置为一对一的关系,那么需要两个类互相有指向对方的引用属性
  public class Book
{
public int BookID { get; set; }
public string Name { get; set; }
public BookCover Cover { get; set; }
} public class BookCover
{
[ Key , ForeignKey ("Coverof" )]
public int BookID { get; set; }
public byte [] Photo { get; set; }
public Book Coverof { get; set; }
}
并且两个类的主键要是一样的,而且为了确认其中一个为关系中的依赖主体,必须用ForeignKey指明,也就是上面的BookCover表的BookID既是外键也必须是主键。否则会报错。
 
关系就讲到这里,如果喜欢就 推荐一下吧~ O(∩_∩)O

EF CodeFirst(四) 关系的更多相关文章

  1. 1.【使用EF Code-First方式和Fluent API来探讨EF中的关系】

    原文链接:http://www.c-sharpcorner.com/UploadFile/3d39b4/relationship-in-entity-framework-using-code-firs ...

  2. EF CodeFirst系列(6)---配置1对1,1对多,多对多关系

    这一节介绍EF CodeFirst模式中的1对0/1,1对多,多对多关系的配置,只有梳理清楚实体间的关系,才能进行愉快的开发,因此这节虽然很简单但是还是记录了一下. 1. 1对0/1关系配置 1. 通 ...

  3. EF Codefirst 中间表(关系表)的增删改查(转)

    EF Codefirst 多对多关系 操作中间表的 增删改查(CRUD)   前言 此文章只是为了给新手程序员,和经验不多的程序员,在学习ef和lambada表达式的过程中可能遇到的问题. 本次使用订 ...

  4. EF CodeFirst系列(2)---CodeFirst的数据库初始化

    1. CodeFirst的默认约定 1.领域类和数据库架构的映射约定 在介绍数据库的初始化之前我们需要先了解领域类和数据库之间映射的一些约定.在CodeFirst模式中,约定指的是根据领域类(如Stu ...

  5. [.NET领域驱动设计实战系列]专题一:前期准备之EF CodeFirst

    一.前言 从去年已经接触领域驱动设计(Domain-Driven Design)了,当时就想自己搭建一个DDD框架,所以当时看了很多DDD方面的书,例如领域驱动模式与实战,领域驱动设计:软件核心复杂性 ...

  6. EF CodeFirst 创建数据库

    最近悟出来一个道理,在这儿分享给大家:学历代表你的过去,能力代表你的现在,学习代表你的将来. 十年河东十年河西,莫欺少年穷 学无止境,精益求精    话说EF支持三种模式:Code First   M ...

  7. 新年奉献MVC+EF(CodeFirst)+Easyui医药MIS系统

    本人闲来无事就把以前用Asp.net做过的一个医药管理信息系统用mvc,ef ,easyui重新做了一下,业务逻辑简化了许多,旨在加深对mvc,ef(codefirst),easyui,AutoMap ...

  8. EF CodeFirst系列(3)---EF中的继承策略(暂存)

    我们初始化数据库一节已经知道:EF为每一个具体的类生成了数据库的表.现在有了一个问题:我们在设计领域类时经常用到继承,这能让我们的代码更简洁且容易管理,在面向对象中有“has  a”和“is a”关系 ...

  9. NetCore2.0下使用EF CodeFirst创建数据库

    本文所使用的VS版本:VS2017 15.3.0 首先新建一个.net core项目  取名NetCoreTask 使用模型视图控制器方式 新建Model层 在Model层下新建一个user实体类 1 ...

随机推荐

  1. Java-String类型的参数传递问题

    刚才看见一个兄弟在为Java的String传值/传引用问题困惑,翻箱倒柜找到了这篇我很久以前写的文章,发在这里,希望能对迷惑的朋友有些帮助. 提要:本文从实现原理的角度上阐述和剖析了:在Java语言中 ...

  2. 常用下载方式的区别-BT下载、磁力链接、电驴

    出处:https://www.jianshu.com/p/72b7a64e5be1 打开 115 离线下载的窗口,看到支持这么多种链接,你都清楚他们是什么原理嘛?接下来我们一个一个说. 一.HTTP( ...

  3. “全栈2019”Java多线程第三十二章:显式锁Lock等待唤醒机制详解

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...

  4. cad2016卸载/安装失败/如何彻底卸载清除干净cad2016注册表和文件的方法

    cad2016提示安装未完成,某些产品无法安装该怎样解决呢?一些朋友在win7或者win10系统下安装cad2016失败提示cad2016安装未完成,某些产品无法安装,也有时候想重新安装cad2016 ...

  5. Spring boot mybatis : Error creating bean with name 'com.github.pagehelper.autoconfigure.MapperAutoConfiguration': Invocation of init method failed;

    报错截图: 解决方法: 只能扫描到自定义的mapper,不能扫描到其他文件. @MapperScan("com.streamax.s17.tms.dao.pper.repository&qu ...

  6. 【liferay】5、使用PortletURL进行跨portlet通信 liferay6.2

    [问题] 1.当我们一个页面存在多一个portlet的时候,如在不同的portlet之间传参? [解决办法] 1.在liferay官方有几种方式,比较复杂麻烦,不是太实用,这里不再赘述. 2.通过fr ...

  7. redis常用命令(二)

    一.集合(set) 单值多value,vaue不能重复 sadd/smembers/sismember 添加数据/获取set所有数据/判断是否存在某个值 scard 获取集合里面的元素个数 srem ...

  8. python实战问题记录

    开发环境搭建 1.安装aiohttp这个异步的http框架失败 提示使用pip更高版本,但是更新之后,还是无法使用.所以,我们采用anaconda中的aiohttp,即打开anaconda,然后进入E ...

  9. git commit --amend的撤销方法

    某同事执行git commit 时太兴奋,执行了 git commit --amend 慌了,不敢编辑上一个commit的description了,直接选择了wq退出,然而git毕竟强大,默认将改动合 ...

  10. python中 =、copy、deepcopy的差别

    python2中,需要import copy模块 python3中,直接可以使用copy()方法,但deepcopy()还是需要导入copy模块 下面以python2为例: 对于"=&quo ...