【译】第5节---Code First约定
原文:http://www.entityframeworktutorial.net/code-first/code-first-conventions.aspx
我们在上一节中已经看到了EF Code-First如何从领域域类创建DB表。 在这里,我们将了解默认的Code-First约定。
什么是约定?
约定是一组默认规则,用于在使用Code-First时自动配置基于领域域类定义的概念模型。 Code-First约定在System.Data.Entity.ModelConfiguration.Conventions命名空间中定义。
让我们看看各种Code-First约定的概述。
类型发现
在上一节中,我们为想要成为模型的一部分的类创建了一个具有DbSet属性的上下文类。 Code-First将为包含为DbSet属性的类创建表,正如我们在上一节中所看到的那样。
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; }
}
以下是一个上下文类,不包括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不被包含在上下文类中的实体集中,Code-First将包含在概念模型中,并为其创建一个DB表,如下所示。

即使上下文类只包含基类作为DbSet属性,Code-First也包括派生类。
类型发现的约定是:
- Code-First包括在上下文类中定义为DbSet属性的类型。
- 代码首先包括实体类型中包含的引用类型,即使它们在不同的程序集中定义。
- Code-First包括派生类,即使只将基类定义为DbSet属性。
主键约定
在上一节中,我们已经看到Code-First在每个表中自动创建一个主键。
主键的默认约定是,如果属性名称为Id或<ClassName> Id(不区分大小写),则Code-First将为属性创建一个主键。
主键属性的数据类型可以是任何东西,但是如果主键属性的类型是数字或GUID,则它将被配置为标识列。
如果您定义了除Id或<ClassName> Id以外的键属性,那么将抛出ModelValidationException。 例如,考虑以下标准(Standard )类:
public class Standard
{
public Standard()
{ }
public int StdId { get; set; }
public string StandardName { get; set; }
public IList<Student> Students { get; set; }
}
像上面的代码中看到的那样,Standard类定义了StdId 键属性。 实体框架将抛出以下异常:
'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将其配置为主键。 我们将在后面的教程中看到如何做。
关系约定
Code-First使用导航属性推断两个实体之间的关系。导航属性可以是简单的引用类型或集合类型。
例如,我们在Standard类中定义了标准导航属性,并在Standard类中定义了ICollection <Student>导航属性。 因此,Code First通过在Students表中插入Standard_StandardId外键列,自动创建标准和学生DB表之间的一对多关系。
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外键创建了以下关系:

因此,关系的默认代码第一约定自动插入带有导航属性名称_导航属性类型的主键名称的外键。比如:Standard_StandardId。
外键约定
上面已经看到,当遇到导航属性时,Code First会自动插入一个外键。建议在关系的从属结尾附加一个外键属性。 请考虑以下示例:
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,它是Standard类中的key属性。
现在,Code First将在Students类中创建StandardId列,而不是Standard_StandardId列,如下所示:

请注意,在上图中,StandardId外键不为空。 这是因为int数据类型不可空。
Code First首先根据外键的可空性来推断关系的多样性。如果属性为空,那么该关系将被注册为null。 否则,该关系注册为NOT NULL。
将StudentId属性的数据类型从int修改为上面的Student类中的Nullable <int>,以在“学生”表中创建一个可空的外键列。
复杂类型约定
Code First为不包含key属性,并且还没有使用DataAnnotation或Fluent API注册主键的类创建复杂类型。
默认Code First约定
下面列出了Code First的默认约定:
1.表名:实体类名称+“s”
2.主键:id或类名+id(不区分大小写)
3.外键:默认情况下,EF将查找与主体实体主键名称相同名称的外键属性。如果不存在,则会创建外键为:导航属性_实体主键名称。(见上文示例)
4.可空列:所有引用类型和可空类型(nullable )
5.不可空列:主键和不可空列
6.数据库列顺序:按照实体类的顺序创建,主键会移动到第一个位置
7.属性映射到数据库:默认所有的属性都会映射到数据库,可以使用[NotMapped]特性进行排除
8.级联删除:所有关系类型默认开启
下表列出了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+为应用程序定义自定义约定。
【译】第5节---Code First约定的更多相关文章
- Code First 约定
Code First 约定 借助 Code First,可通过使用 C# 或 Visual Basic .NET 类来描述模型.模型的基本形状可通过约定来检测.约定是规则集,用于在使用 Code Fi ...
- Entity Framework 6新特性:全局性地自定义Code First约定
2012年12月11日,Entity Framework已经发布了Entity Framework 6 Alpha2,因项目需要,目前已使用了其中的两个特性,今天就来介绍一下第一个特性:全局性地自定义 ...
- EF6.0 自定义Code First约定
自定义Code First约定有三种方式,分别是:Lightweight Conventions(轻量级约定).Configuration Conventions(配置型约定).Model-based ...
- EntityFramWork(3 code First 约定)
Code First 约定 借助 Code First,可通过使用 C# 或 Visual Basic .NET 类来描述模型.模型的基本形状可通过约定来检测.约定是规则集,用于在使用 Code ...
- EntityFramework Code-First 简易教程(二)-------Code First约定
Code First 约定 在前一篇中,我们已经知道了EF Code-First怎样从模型类(domain classes)中创建数据库表,下面,我们开始学习默认的Code-First约定. 什么是约 ...
- 【EF】Entity Framework 6新特性:全局性地自定义Code First约定
应用场景 场景一:EF Code First默认使用类名作为表名,如果我们需要给表名加个前缀,例如将类名Category映射到表Shop_Category.将Product映射到Shop_Produc ...
- Code First约定-数据注释
通过实体框架Code First,可以使用您自己的域类表示 EF 执行查询.更改跟踪和更新函数所依赖的模型.Code First 利用称为“约定先于配置”的编程模式.这就是说,Code First 将 ...
- 【译】第43节---EF6-自定义约定
原文:http://www.entityframeworktutorial.net/entityframework6/custom-conventions-codefirst.aspx Code-Fi ...
- Entity Framework Code First约定
Code First使你能够通过C# 或者 Visual Basic .NET来描述模型,模型的基本规则通过使用约定来进行检查,而约定就是一系列内置的规则. 在Code First中基于类的定义通过一 ...
随机推荐
- Vuejs vm对象详解
Vuejs vm对象详解 vue数据是怎么驱动视图的?一堆数据放在那里是不会有任何作用的,它必须通过我们的View Model(视图模型)才能操控视图. 图中的model其实就是数据,一般我们写成js ...
- Node.js中环境变量process.env详解
Node.js中环境变量process.env详解process | Node.js API 文档http://nodejs.cn/api/process.html官方解释:process 对象是一个 ...
- 【JavaScript 6连载】六、认识原型
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" ...
- 详解BOM头以及去掉BOM头的方法--踩过BOM的大坑
类似WINDOWS自带的记事本等软件,在保存一个以UTF-8编码的文件时,会在文件开始的地方插入三个不可见的字符(0xEF 0xBB 0xBF,即BOM).它是一串隐藏的字符,用于让记事本等编辑器识别 ...
- Java程序员秋招面经大合集(BAT美团网易小米华为中兴等)
Cvte提前批 阿里内推 便利蜂内推 小米内推 金山wps内推 多益网络 拼多多学霸批 搜狗校招 涂鸦移动 中国电信it研发中心 中兴 华为 苏宁内推 美团内推 百度 腾讯 招商银行信用卡 招银网络科 ...
- linux下启动多个php,分别监听不同的端口。
在工作中,我们可能会遇到,服务器集群的搭建. 这个时候,我们不可能,每一台服务器都是lnmp的环境,我们会把nmp分别放在不同的服务器上,不同的服务器负责不同的功能.比如我们下面要说的php 加入ng ...
- Prometheus监控学习笔记之Prometheus不完全避坑指南
0x00 概述 Prometheus 是一个开源监控系统,它本身已经成为了云原生中指标监控的事实标准,几乎所有 k8s 的核心组件以及其它云原生系统都以 Prometheus 的指标格式输出自己的运行 ...
- 判断PC或mobile设备
js 限制: <script type="text/javascript"> function uaredirect(f){try{if(document.getEle ...
- P1501 [国家集训队]Tree II(LCT)
P1501 [国家集训队]Tree II 看着维护吧2333333 操作和维护区间加.乘线段树挺像的 进行修改操作时不要忘记吧每个点的点权$v[i]$也处理掉 还有就是$51061^2=2607225 ...
- fjwc2019
机房搬迁.......再加上文化课.......咕了十几天才有空补上....... day0听一个教授讲理论......在学长的带领下咕掉了..... D1 T1:#178. 「2019冬令营提高组」 ...