• Code First 约定

  在前一篇中,我们已经知道了EF Code-First怎样从模型类(domain classes)中创建数据库表,下面,我们开始学习默认的Code-First约定。

什么是约定?

  约定就是在Code-First模式中自动配置模型类的默认规则,Code-First约定定义在System.Data.Entity.ModelConfiguration.Conventions 命名空间

让我们来看看各种约定的概述

类型发现(Type Discovery):

  在前一篇中,我们创建了一个context类并在其里面添加DbSet<T>属性,T为我们想要操作的模型类。Code-First会包括任何在这个类中的引用类型,就算这个引用类型的定义在其他不同集合中也是如此。

举个例子,下面的Student实体类有引用了Teacher类的属性,然而context并没有包含Teacher的DbSet属性。

public class Student
{
public Student()
{ }
public int StudentID { get; set; }
public string StudentName { get; set; }
public DateTime DateOfBirth { get; set; }
public byte[] Photo { get; set; }
public decimal Height { get; set; }
public float Weight { get; set; } public Teacher Teacher { get; set; } public Standard Standard { get; set; }
} public class Teacher
{
public Teacher()
{ }
public int TeacherId { get; set; }
public string TeacherName { get; set; }
}

context并没有包含Teacher的DbSet属性

namespace EF_Code_First_Tutorials
{ public class SchoolContext: DbContext
{
public SchoolContext(): base()
{ } public DbSet<Student> Students { get; set; }
public DbSet<Standard> Standards { get; set; } }
}

所以,即使Teacher类没有被包含在context的一个DbSet中,Code-First依然会创建一个Teachers表,如下图所示

即使context仅包含基类(base class)作为DbSet属性,Code-First也会包含它的派生类(derived class)

总结,类型发现(type discovery)约定是:

  1. Code-First 包含的类型作为一个DbSet属性被定义在context类中(Code-First includes types defined as a DbSet property in context class.)
  2. Code-First 包含的引用类型被包含在实体类型中,即使它被定义在不同的集合里(Code-First includes reference types included in entity types even if they are defined in different assembly.)
  3. Code-First 包含了派生类,即使只有它的基类作为DbSet属性被定义(Code-First includes derived classes even if only the base class is defined as DbSet property.)
  • 主键(Primary Key) 约定

  在上一篇中,我们看见Code-First自动在每张表里创建主键。这里的主键约定是:Code-First会自动把属性名称为Id或者<class name>Id(不区分大小写)的属性创建为主键,主键属性的数据类型可以是任何类型,但是如果主键属性的类型是数字或者GUID,则会将其定义成一个标识列(identity column)。

  如果你已经定义了键属性是除了Id或者<ClassName>Id的其他名称,则会抛出一个ModelValidationException异常,考虑如下代码

public class Standard
{
public Standard()
{ }
public int StdId { get; set; }
public string StandardName { get; set; } public IList<Student> Students { get; set; } }
}

如上所示,Standard类定义了StdId作为键属性,Entity Framework将抛出如下异常:

'System.Data.Entity.ModelConfiguration.ModelValidationException' occurred in EntityFramework.dll
EntityType 'Standard' has no key defined. Define the key for this EntityType.

如果你非要定义StdId作为主键,那你必须使用DataAnnotations或者Fluent API去配置它成为主键,我们将在后面的章节学习到。

  • 关系(Relationship) 约定

  Code First使用导航属性(navigation property)在两个实体之间推断关系,导航属性是一种简单的引用类型或者集合类型。举个例子,我们在Student类中定义Standard导航属性,在Stardard类中定义ICollention<Student>导航属性,所以Code First可以自动在数据库中的Standards表和Students表之间创建一对多的关系并在Students表中插入Standard_StandardId外键列。

public class Student
{
public Student()
{ }
public int StudentID { get; set; }
public string StudentName { get; set; }
public DateTime DateOfBirth { get; set; }
public byte[] Photo { get; set; }
public decimal Height { get; set; }
public float Weight { get; set; } //Navigation property
public Standard Standard { get; set; }
} public class Standard
{
public Standard()
{ }
public int StandardId { get; set; }
public string StandardName { get; set; } //Collection navigation property
public IList<Student> Students { get; set; } }

上面的实体使用Standard_StandardId作为外键创建如下关系

因此,默认的code first关系约定会自动插入外键,用<navigation property Name>_<primary key property name of navigation property type>这种格式,比如 Standard_StandardId

  • 外键(Foreign key) 约定

我们在上面看到了通过导航属性,Code Frist可以自动插入外键。但这里建议在关系末尾包含一个独立的外键属性。考虑如下代码:

public class Student
{
public Student()
{ }
public int StudentID { get; set; }
public string StudentName { get; set; }
public DateTime DateOfBirth { get; set; }
public byte[] Photo { get; set; }
public decimal Height { get; set; }
public float Weight { get; set; } //Foreign key for Standard
public int StandardId { get; set; } public Standard Standard { get; set; }
} public class Standard
{
public Standard()
{ }
public int StandardId { get; set; }
public string StandardName { get; set; } public IList<Student> Students { get; set; } }

正如我们看到的,Student类包含了外键StandardId,而StandardId是Standard类的主键,现在,Code First将会在Students表中创建一个StandardId列来代替Standard_StandardId列,如下所示

注意:StandardId外键不能为空,因为int数据类型不可为空

Code First 根据不可为空的外键推断多重关系,除非外键属性为空然后关系被注册为空,否则,外键属性不为空(NOT NULL)。也可以把Student类StandardId属性的数据类型从int修改成Nullable<int>来创建一个外键可为空的Students表。

  • 复杂类型(Complex type) 约定

Code First 给类创建不包含键属性,而且主键没有被注册的复杂类型,这个时候使用DataAnnotation或者Fluent API。

  • 默认Code-First 约定表

Default Convention For Description
Table Name <Entity Class Name> + 's' 
EF will create DB table with entity class name suffixed by 's'
Primary key Name 1) Id 
2) <Entity Class Name> + "Id" (case insensitive)

EF will create primary key column for the property named Id or <Entity Class Name> + "Id" (case insensitive)

Foreign key property Name By default EF will look for foreign key property with the same name as principal entity primary key name. 
If foreign key property does not exists then EF will create FK column in Db table with <Dependent Navigation Property Name> + "_" + <Principal Entity Primary Key Property Name> 
e.g. EF will create Standard_StandardId foreign key column into Students table if Student entity does not contain foreignkey property for Standard where Standard contains StandardId
Null column EF creates null column for all reference type properties and nullable primitive properties.
Not Null Column EF creates NotNull columns for PrimaryKey properties and non-nullable value type properties.
DB Columns order EF will create DB columns same as order of properties in an entity class. However, primary key columns would be moved first.
Properties mapping to DB By default all properties will map to database. Use [NotMapped] attribute to exclude property or class from DB mapping.
Cascade delete Enabled By default for all types of relationships.

下面的表列出了C#数据类型映射到SQL的数据类型,和主键列的数据类型以及长度

C# DataType Related DB Column DataType PK Column DataType & Length
int int int, Identity column increment by 1
string nvarchar(Max) nvarchar(128)
decimal decimal(18,2) decimal(18,2)
float real real
byte[] varbinary(Max) varbinary(128)
datetime datetime datetime
bool bit bit
byte tinyint tinyint
short smallint smallint
long bigint bigint
double float float
char No mapping No mapping
sbyte No mapping 
(throws exception)
No mapping
object No mapping No mapping

这是篇对code first约定的概述,这里的约定也能用DataAnnotation和Fluent API重写。在EF6.0里,你也可以使用自定义约定。

学完这篇,相信大家也对“约定大于配置”这种设计理念也有感知了吧^_^

下一篇我们将学习怎样初始化数据库,嗯,先睡觉了

EntityFramework Code-First 简易教程(二)-------Code First约定的更多相关文章

  1. WebGL简易教程(二):向着色器传输数据

    目录 1. 概述 2. 示例:绘制一个点(改进版) 1) attribute变量 2) uniform变量 3) varying变量 3. 结果 4. 参考 1. 概述 在上一篇教程<WebGL ...

  2. Entity Frame Code First 简易教程

    简介 什么是ORM 搭建Entity FrameWork CodeFirst应用 数据库迁移 表属性常见配置 Entity FrameWork 一对多.多对多 一.简介 Entity Framewor ...

  3. PySide 简易教程<二>-------工欲善其事,必先利其器

    OK , 在Linux的开发环境下,对于我们的简短的PySide程序而言,不需要使用QtCreator,使用文本编辑器.之所以,使用文本编辑器,是因为小应用代码量很少,更重要的是一行行的写可以加深我们 ...

  4. Dart 语言简易教程系列

    google Fuchsia系统 及 dart语言简介 在 InteIIiJ IDEA 中搭建 Dart 的开发环境 Dart Linux 开发环境搭建 Dart 语言简易教程(一) Dart 语言简 ...

  5. WebGL简易教程(三):绘制一个三角形(缓冲区对象)

    目录 1. 概述 2. 示例:绘制三角形 1) HelloTriangle.html 2) HelloTriangle.js 3) 缓冲区对象 (1) 创建缓冲区对象(gl.createBuffer( ...

  6. WebGL简易教程(四):颜色

    目录 1. 概述 2. 示例:绘制三角形 1) 数据的组织 2) varying变量 3. 结果 4. 理解 1) 图形装配和光栅化 2) 内插过程 5. 参考 1. 概述 在上一篇教程<Web ...

  7. WebGL简易教程——目录

    目录 1. 绪论 2. 目录 3. 资源 1. 绪论 最近研究WebGL,看了<WebGL编程指南>这本书,结合自己的专业知识写的一系列教程.之前在看OpenGL/WebGL的时候总是感觉 ...

  8. mysql进阶(二)索引简易教程

    Mysql索引简易教程 基本概念 索引是指把你设置为索引的字段A的内容储存在一个独立区间S里,里面只有这个字段的内容.在找查这个与这个字段A的内容时会直接从这个独立区间里查找,而不是去到数据表里查找. ...

  9. Ocelot简易教程(二)之快速开始2

    为什么这篇的标题叫"Ocelot简易教程(二)之快速开始2"呢,因为很多朋友跟我说上一篇" Ocelot简易教程(二)之快速开始1"内容太少了,只是简单介绍Oc ...

  10. Ocelot简易教程(二)之快速开始1

    Ocelot简易教程目录 Ocelot简易教程(一)之Ocelot是什么 Ocelot简易教程(二)之快速开始1 Ocelot简易教程(二)之快速开始2 Ocelot简易教程(三)之主要特性及路由详解 ...

随机推荐

  1. windows平台,实现录音功能详解

    音频处理分为播放和录音两类.对这些处理,微软提供了一些列函数,称之为Waveform Functions.这篇文章讨论录音功能.会对微软提供的函数做简单说明,并对这些函数封装成c++类,再进一步封装成 ...

  2. Hadoop2源码分析-准备篇

    1.概述 我们已经能够搭建一个高可用的Hadoop平台了,也熟悉并掌握了一个项目在Hadoop平台下的开发流程,基于Hadoop的一些套件我们也能够使用,并且能利用这些套件进行一些任务的开发.在Had ...

  3. 最短路径算法----Dijkstra (转)

    Dijkstra算法的核心思想是贪心策略+动态规划 算法流程: 在以下说明中,s为源,w[u,v]为点u和v之间的边的长度,结果保存在dis[] 初始化:源的距离dis[s]设为0,其他的点距离设为无 ...

  4. 制作openstack使用的Ubuntu镜像

    一.环境准备 OS:Ubuntu-14.04 制作镜像版本:Ubuntu-14.04.4-server-amd64.iso 查看是否支持虚拟化(有输出代表支持,否则在BIOS页面中设置即可): egr ...

  5. Java设计模式学习记录-建造者模式

    前言 今天周末,有小雨,正好也不用出门了,那就在家学习吧,经过了两周的面试,拿到了几个offer,但是都不是自己很想去的那种,要么就是几个人的初创小公司,要么就是开发企业内部系统的这种传统开发,感觉这 ...

  6. V8源码边缘试探-黑魔法指针偏移

    这博客是越来越难写了,参考资料少,难度又高,看到什么写什么吧! 众多周知,在JavaScript中有几个基本类型,包括字符串.数字.布尔.null.undefined.Symbol,其中大部分都可以在 ...

  7. [转]Magento Configurable Product

    本文转自:https://docs.magento.com/m1/ce/user_guide/catalog/product-configurable.html A configurable prod ...

  8. Linux下安装SQL Server 2016(准备篇SQL Server on linux)

    要在Linux安装sql server,首先的先有linux,下面会讲下载,然后安装Linux. 一.下载centos 7.2 : Centos 7.2下载 大概4G左右,这个链接的下载速度还是非常快 ...

  9. SpringCloud高可用和高并发

    1 高可用 什么是高可用:(High Availability)在一个长时间内服务不受影响.通俗的讲就是,一个机器挂掉的时候,有其他机器可以继续提供同样的服务. 如何实现高可用:冗余+自动故障转移.冗 ...

  10. Linux常用基本命令( ls, alias)

    ls命令 作用:列举目录文件信息( list directory content ) 格式:ls [option] [file] 1,命令不跟任何选项与目录,表示列举当前目录的文件信息 ghostwu ...