目录

1.前言

2.约定

2.1 主键约定

2.2 关系约定

2.3 复杂类型约定

3.数据注释

3.1 主键

3.2 必需

3.3 MaxLength和MinLength

3.4 NotMapped

3.5 复杂属性

3.6 ConcurrencyCheck

4.Fluent API

5.总结

前言  

  在之前的Code First示例中,我们编写好代码直接运行,就自动会自定创建数据库,并且根据定义好的类创建了对应的表,更加神奇的时候竟然还能自动创建主键、外键等等。这是如何实现的呢?如果我们想指定特定的属性为主键又该如何实现呢? 

约定  

  其实Code First生成模型的时候会通过约定(Conventions)来检测,约定实际上是EF定义的一组规则集,用于在使用Code First时根据这些规则生成模型,是在System.Data.Entity.ModelConfiguration.Convertions命名空间中定义的,我们可以去扩展约定,当然也可以不是使用内置的约定。EF内置约定如下:

  

  从上图我们可以看到定义了复杂属性预定、外键预定、主键约定,当然还有很多很多,EF也一直扩充内置约定。

  

  主键约定  

  如果类的属性名为“ID”(不区分大小写)或者类名的后面跟有“ID”,则Code First会推断该属性是主键。如果主键属性的类型为数值或者GUID,则将其配置为标识列。

  

  如上图所示,DepartmentID会被约定为主键。

  关系约定  

  如果类A中的属性中包含他类B的属性(该属性在类B本身中约定为主键),并且类A中包含类B,则Code First会自动推断出关联关系,并确定外键。

  

  如上图所示,在DepartmentID在Course表中会定义为外键,并且Department表和Course表会自动建立关联关系。

  

  复杂类型约定

  当Code First无法推断出主键,并没有通过其他方式设置主键,则该类型会被自动当做复杂属性。对于以下类定义,Code First推断Details是复杂属性,因为它没有主键。

  

  更多参考:https://msdn.microsoft.com/zh-cn/library/jj679962(v=vs.113).aspx

数据注释  

  默认情况下,Code First会根据约定定义模型,但是默认的约定规则毕竟有限,Code First同样允许通过数据注释来定义模型,而且如果没有移除约定的话,会先通过约定定义,再通过数据注释来定义,那么数据注释是如何实现的呢?

  主键  

  类中需要通过数据注释来定义主键,非常简单,只需要在对应的属性上面加上KEY关键字,如下所示:

  

  必需  

  属性上面加上Requied关键字,说明这个属性是必需的,即不允许为空。

  

  MaxLength和MinLength  

  使用MaxLength和MinLength特性,可以限定字段的范围。

  

  上图定义BloggerName长度为5-10。

  NotMapped  

  不映射,顾名思义就是不会将类的属性映射到数据库表的字段上,标记了NotMapped特性不会在数据库表中生成对应的字段。

  

  复杂属性  

  在类名上面增加ComplexType特性,并且其他类中某属性为该类时,该类映射到数据时就会变成复杂属性。

  

  

  Blog类中添加一个属性为BlogDetails。

public BlogDetails BlogDetail { get; set; }

    

  ConcurrencyCheck  

  ConcurrencyCheck注释可用于标记要在用户编辑或删除实体时用于在数据库中进行并发检查的一个或多个属性。

    

  调用 SaveChanges 时,因为 BloggerName 字段上具有 ConcurrencyCheck 注释,所以在更新中将使用该属性的初始值。该命令将尝试通过同时依据键值和 BloggerName 的初始值进行筛选来查找正确的行。下面是发送到数据库的 UPDATE 命令的关键部分,在其中您可以看到该命令将更新 PrimaryTrackingKey 为 1 且 BloggerName 为“Julie”(这是从数据库中检索到该博客时的初始值)的行。

  

  如果在此期间有人更改了该博客的博主姓名,则此更新将失败,并引发 DbUpdateConcurrencyException 并且需要处理该异常。

  

  更多参考:https://msdn.microsoft.com/zh-cn/library/jj591583(v=vs.113).aspx

Fluent API  

  Code First模式下,默认行为是使用一组EF内嵌的约定规则将类映射到表。但有时候约定无法满足需求,这是我们还可以通过数据注释的方式来实现,但是数据注释功能仍然有限,好在EF提供了更加灵活的方式——Fluent API。

  Fluent API功能非常强大,它在通过重写DbContext上的OnModelCreating方法来实现自定义规则,可以设置主键、组合主键、外键、指定长度、指定属性是否映射到表等等。

  

  

  更多参考:https://msdn.microsoft.com/zh-cn/library/jj591617(v=vs.113).aspx

总结

  既然EF内置了很多约定规则,为何又可以通过数据注释方式来定义模型,而且还可以通过功能更加强大的Fluent API自定义模型。

  虽然内置的约定规则非常多,而且我想微软以后还会不断加入更多的约定,但是这些约定毕竟还是有限的,不能够满足所有用户需求,所以允许通过数据注释的方式来增加定义模型,但是有些情况通过数据注释依然是无法满足(例如:一个类型生成一张表还是多张表),这是我们可以通过Fluent API在生成模型之前自定义模型。

  综上所述,我们得知这三种定义模型的优先级为:约定—>数据注释—>Fluent API。

  

ORM系列之二:EF(4) 约定、注释、Fluent API的更多相关文章

  1. 10.翻译系列:EF 6中的Fluent API配置【EF 6 Code-First系列】

    原文链接:https://www.entityframeworktutorial.net/code-first/fluent-api-in-code-first.aspx EF 6 Code-Firs ...

  2. WPF技术触屏上的应用系列(二): 嵌入百度地图、API调用及结合本地数据库在地图上进行自定义标点的实现

    原文:WPF技术触屏上的应用系列(二): 嵌入百度地图.API调用及结合本地数据库在地图上进行自定义标点的实现 去年某客户单位要做个大屏触屏应用,要对档案资源进行展示之用.客户端是Window7操作系 ...

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

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

  4. EF Core中通过Fluent API完成对表的配置

    EF Core中通过Fluent API完成对表的配置 设置实体在数据库中的表名 通过ToTable可以为数据模型在数据库中自定义表名,如果不配置,则表名为模型名的复数形式 public class ...

  5. ORM系列之二:EF(2)Code First

    目录 1. Code First是什么? 2. Code First 简单示例 3. 数据存储 4. 迁移 Code First是什么 Code First 顾名思义就是先写代码,当然不是乱写,而是按 ...

  6. ORM系列之二:EF(1)

    目录 1. EF是什么 2. 如何获取EF 3. EF有哪些主要模式 EF是什么 EF全称为Entity Framework,是微软推荐的一种数据库访问技术,属于重量级的ORM框架,功能非常强大,目前 ...

  7. ORM系列之二:EF(5) Model First

    前面我们已经介绍过EF中Code First开发模式,简而言之,就是不管三七二十一直接写代码,不过对于很多开发人员来说,可能并不习惯这样来开发,并且安装标准的开发流程,应该是先建模再进行编码,当然EF ...

  8. ORM系列之二:EF(3) 数据库连接

    目录 1.前言 2.Code First默认连接 3.Code First指定数据库 4.自定义连接 前言 在介绍EF的Code First模式时候,我们没有修改任何配置,运行之后自动在LocalDb ...

  9. java se系列(二) 关键字、注释、常量、进制转换、变量、数据类型转换、运算符

    1 关键字 1.1 关键字的概述 Java的关键字对java的编译器有特殊的意义,他们用来表示一种数据类型,或者表示程序的结构等,关键字不能用作变量名.方法名.类名.包名. 1.2 常见的关键字 备注 ...

随机推荐

  1. int main( int argc, char **argv)

    1.参数 (有时参数是void) argc是程序运行时参数个数 argv是存储参数的数组,可以用char* argv[],也可以用char **argv. 例如编译一个hello.c的程序 1 #in ...

  2. 数据库Blob数据类型转String

    blob数据是存储大对象数据类型, 一般存放二进制的,所以才用字节存取. 首先判断blob数据是否为空,然后采用输入流读出数据,具体代码如下: String content = null; try { ...

  3. RAD Studio 2009-10Seattle IDE Fix Pack 5.94

    IDE Fix Pack 5.94 IDE Fix Pack is a collection of unofficial bug fixes and performance optimizations ...

  4. R平方

    参考其他网页 通常R2越大越好,但看到亦在后面标上P值,这两者之间有何联系? R2和p值没有必然联系.就像你做线性分析和(单因素或多因素)方差分析一样,若A和K线性相关,也有可能A对K么有显著性影响一 ...

  5. scala安装

    一:在官网下载相应的版本http://www.scala-lang.org/download/2.10.6.html 二,在linux中解压下载下来的scala包   三:配置环境变量 export ...

  6. Servlet 单例多线程

    Servlet如何处理多个请求访问? Servlet容器默认是采用单实例多线程的方式处理多个请求的: 1.当web服务器启动的时候(或客户端发送请求到服务器时),Servlet就被加载并实例化(只存在 ...

  7. RAC出现CRS-4535: Cannot communicate with Cluster Ready Services 时排查问题步骤

    crsctl check crs 发现第二行报错: CRS-4638: Oracle High Availability Services is onlineCRS-4535: Cannot comm ...

  8. react native TextInput

    今天我想说一下react native中的一个控件,TextInput 翻译过来就是文本输入,对应着android中的EditText.我们先看一下官方是怎样描述的.TextInput是一个允许用户在 ...

  9. 读取EXCEL数据到内存DataTable

    protected void Page_Load(object sender, EventArgs e) { string filepath = Server.MapPath("~/file ...

  10. HDU5730 Shell Necklace(DP + CDQ分治 + FFT)

    题目 Source http://acm.hdu.edu.cn/showproblem.php?pid=5730 Description Perhaps the sea‘s definition of ...