原文: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也包括派生类。

类型发现的约定是:

  1. Code-First包括在上下文类中定义为DbSet属性的类型。
  2. 代码首先包括实体类型中包含的引用类型,即使它们在不同的程序集中定义。
  3. 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约定的更多相关文章

  1. Code First 约定

    Code First 约定 借助 Code First,可通过使用 C# 或 Visual Basic .NET 类来描述模型.模型的基本形状可通过约定来检测.约定是规则集,用于在使用 Code Fi ...

  2. Entity Framework 6新特性:全局性地自定义Code First约定

    2012年12月11日,Entity Framework已经发布了Entity Framework 6 Alpha2,因项目需要,目前已使用了其中的两个特性,今天就来介绍一下第一个特性:全局性地自定义 ...

  3. EF6.0 自定义Code First约定

    自定义Code First约定有三种方式,分别是:Lightweight Conventions(轻量级约定).Configuration Conventions(配置型约定).Model-based ...

  4. EntityFramWork(3 code First 约定)

      Code First 约定 借助 Code First,可通过使用 C# 或 Visual Basic .NET 类来描述模型.模型的基本形状可通过约定来检测.约定是规则集,用于在使用 Code ...

  5. EntityFramework Code-First 简易教程(二)-------Code First约定

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

  6. 【EF】Entity Framework 6新特性:全局性地自定义Code First约定

    应用场景 场景一:EF Code First默认使用类名作为表名,如果我们需要给表名加个前缀,例如将类名Category映射到表Shop_Category.将Product映射到Shop_Produc ...

  7. Code First约定-数据注释

    通过实体框架Code First,可以使用您自己的域类表示 EF 执行查询.更改跟踪和更新函数所依赖的模型.Code First 利用称为“约定先于配置”的编程模式.这就是说,Code First 将 ...

  8. 【译】第43节---EF6-自定义约定

    原文:http://www.entityframeworktutorial.net/entityframework6/custom-conventions-codefirst.aspx Code-Fi ...

  9. Entity Framework Code First约定

    Code First使你能够通过C# 或者 Visual Basic .NET来描述模型,模型的基本规则通过使用约定来进行检查,而约定就是一系列内置的规则. 在Code First中基于类的定义通过一 ...

随机推荐

  1. python中从键盘输入内容的方法raw_input()和input()的区别

    raw_input()输出结果都是字符串 Input()输入什么内容,输出就是什么内容

  2. Django框架----模板语法

    Django模板系统 官方文档 一.什么是模板? 只要是在html里面有模板语法就不是html文件了,这样的文件就叫做模板. 二.模板语法分类 只需要记两种特殊符号: {{  }}和 {% %} 变量 ...

  3. 2019/3/20 wen 流程控制

  4. MySQL笔记(八)存储过程练习&补充

    存储过程有什么优缺点?为什么要用存储过程?或者在什么情况下才用存储过程? 最直白的好处是存储过程比较快. 1.利用存储过程,给Employee表添加一条业务部门员工的信息. DROP PROCEDUR ...

  5. mycat中schema.xml的一些解释

    <?xml version="1.0"?> <!DOCTYPE mycat:schema SYSTEM "schema.dtd"> &l ...

  6. MySQL 跨库主从

    一个线上需求,要求主从两库的数据库名字不一样, 在从库上做如下配置: replicate-rewrite-db=DB_1->DB_1_online replicate-rewrite-db=DB ...

  7. 统计py文件中的代码行

    希望是输入一个合法的文件夹的路径,然后代码自动读取该文件夹下的每个py结尾的文件内的代码行数,最后汇总一个数,但现在只是有思路,却没时间写,这是能读取同级文件下的某个文件, with open('te ...

  8. Python学习基础(三)——装饰器,列表生成器,斐波那契数列

    装饰器——闭包 # 装饰器 闭包 ''' 如果一个内部函数对外部(非全局)的变量进行了引用,那么内部函数被认为是闭包 闭包 = 函数块 + 定义时的函数环境 ''' def f(): x = 100 ...

  9. html5-表单属性及<!DOCTYPE> 标签

    <!DOCTYPE> 标签定义和用法<!DOCTYPE> 声明必须位于HTML 5 文档中的第一行,也就是位于<html> 标签之前.该标签告知浏览器文档所使用的H ...

  10. windows2012R2标准版升级到数据中心版,不用重装系统

    windows2012R2标准版升级到数据中心版,不用重装系统 Windows Server 2012 R2是微软的服务器系统,是 Windows Server 2012 的升级版本. Windows ...