【译】第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中基于类的定义通过一 ...
随机推荐
- 面试题-JAVA算法题
1.编写一个程序,输入n,求n!(用递归的方式实现). public static long fac(int n){ if(n<=0) return 0; else if(n==1) retur ...
- mac shell终端编辑命令行快捷键——行首,行尾
Ctrl + d 删除一个字符,相当于通常的Delete键(命令行若无所有字符,则相当于exit:处理多行标准输入时也表示eof) Ctrl + h 退格删除一个字符,相当 ...
- 关于web.xml中配置Spring字符编码过滤器以解决中文乱码的问题
当出现中文乱码问题,Spring中可以利用CharacterEncodingFilter过滤器解决,如下代码所示: <!-- Spring字符编码过滤器:解决中文乱码问题 --> < ...
- Linux指令之netstat
查看某个端口的连接数 netstat -nat | grep -iw "8463" | wc -l [Mac&Redhat通用] 查看连接状况 netstat -nat | ...
- linux 函数库使用
程序函数库可分为3种类型:静态函 数库(static libraries).共享函数库(shared libraries)和动态加载函数库(dynamically loaded libraries) ...
- MQ选型对比RabbitMQ RocketMQ ActiveMQ Kafka(外加redis对比及其实现)
rocketmq 4.3开始支持事务https://www.cnblogs.com/hzmark/p/rocket_txn.html 参考:rabbitMQ.activeMQ.zeroMQ.Kafka ...
- 火车时刻表WebApp
关键词 :Ajax 跨域访问 php 同源策略 JQueryMobile 前言 在面试的过程中,兄弟连的徐老师提出要求我用JQuery Mobile(前端框架)来实现一个具有“火车时刻表”功能的Web ...
- CC攻击介绍及如何防御
CC攻击介绍 CC攻击(Challenge Collapsar)是DDOS(分布式拒绝服务)的一种,前身名为Fatboy攻击,也是一种常见的网站攻击方法.攻击者借助代理服务器生成指向受害主机的合 ...
- 对客户端攻击:adobe_toolbutton
对客户端攻击:adobe_toolbutton 漏洞简介 远程攻击者可以利用漏洞执行任意指令.当用户打开特定pdf就可以触发payload. 实践过程 输入命令use exploit/windows/ ...
- Codeforces 37D Lesson Timetable - 组合数学 - 动态规划
题目传送门 神奇的门I 神奇的门II 题目大意 有$n$组学生要上课2次课,有$m$个教室,编号为$1$到$m$.要确定有多少种不同的安排上课的教室的方案(每组学生都是本质不同的),使得它们满足: 每 ...