原文: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属性。

  1. public class Student
  2. {
  3. public Student()
  4. {
  5.  
  6. }
  7. public int StudentID { get; set; }
  8. public string StudentName { get; set; }
  9. public DateTime DateOfBirth { get; set; }
  10. public byte[] Photo { get; set; }
  11. public decimal Height { get; set; }
  12. public float Weight { get; set; }
  13.  
  14. public Teacher Teacher { get; set; }
  15.  
  16. public Standard Standard { get; set; }
  17. }
  18.  
  19. public class Teacher
  20. {
  21. public Teacher()
  22. {
  23.  
  24. }
  25. public int TeacherId { get; set; }
  26. public string TeacherName { get; set; }
  27. }

以下是一个上下文类,不包括Teacher作为DbSet属性(实体集)

  1. namespace EF_Code_First_Tutorials
  2. {
  3.  
  4. public class SchoolContext: DbContext
  5. {
  6. public SchoolContext(): base()
  7. {
  8.  
  9. }
  10.  
  11. public DbSet<Student> Students { get; set; }
  12. public DbSet<Standard> Standards { get; set; }
  13.  
  14. }
  15. }

因此,即使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 )类:

  1. public class Standard
  2. {
  3. public Standard()
  4. {
  5.  
  6. }
  7. public int StdId { get; set; }
  8. public string StandardName { get; set; }
  9. public IList<Student> Students { get; set; }
  10. }

像上面的代码中看到的那样,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表之间的一对多关系。

  1. public class Student
  2. {
  3. public Student()
  4. {
  5.  
  6. }
  7. public int StudentID { get; set; }
  8. public string StudentName { get; set; }
  9. public DateTime DateOfBirth { get; set; }
  10. public byte[] Photo { get; set; }
  11. public decimal Height { get; set; }
  12. public float Weight { get; set; }
  13.  
  14. //Navigation property
  15. public Standard Standard { get; set; }
  16. }
  17.  
  18. public class Standard
  19. {
  20. public Standard()
  21. {
  22.  
  23. }
  24. public int StandardId { get; set; }
  25. public string StandardName { get; set; }
  26.  
  27. //Collection navigation property
  28. public IList<Student> Students { get; set; }
  29.  
  30. }

上述实体使用Standard_StandardId外键创建了以下关系:

因此,关系的默认代码第一约定自动插入带有导航属性名称_导航属性类型的主键名称的外键。比如:Standard_StandardId。

外键约定

上面已经看到,当遇到导航属性时,Code First会自动插入一个外键。建议在关系的从属结尾附加一个外键属性。 请考虑以下示例:

  1. public class Student
  2. {
  3. public Student()
  4. {
  5.  
  6. }
  7. public int StudentID { get; set; }
  8. public string StudentName { get; set; }
  9. public DateTime DateOfBirth { get; set; }
  10. public byte[] Photo { get; set; }
  11. public decimal Height { get; set; }
  12. public float Weight { get; set; }
  13.  
  14. //Foreign key for Standard
  15. public int StandardId { get; set; }
  16.  
  17. public Standard Standard { get; set; }
  18. }
  19.  
  20. public class Standard
  21. {
  22. public Standard()
  23. {
  24.  
  25. }
  26. public int StandardId { get; set; }
  27. public string StandardName { get; set; }
  28.  
  29. public IList<Student> Students { get; set; }
  30.  
  31. }

在上面的代码中可以看到,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. Linux基础命令---pgrep

    pgrep pgrep指令可以按名字或者其他属性搜索指定的进程,显示出进程的id到标准输出. 此命令的适用范围:RedHat.RHEL.Ubuntu.CentOS.SUSE.openSUSE.Fedo ...

  2. OAuth2.0 知多少(好)

    https://www.cnblogs.com/sheng-jie/p/6564520.html 简书集成的社交登录,大大简化了我们的注册登录流程,真是一号在手上网无忧啊.这看似简单的集成,但背后的技 ...

  3. vue路由3:子路由

    <div id="app"> <div> <router-link to="/">首页</router-link> ...

  4. HDU 1527 取石子游戏 (威佐夫博弈)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1527 有两堆石子,数量任意,可以不同.游戏开始由两个人轮流取石子.游戏规定,每次有两种不同的取法,一是 ...

  5. python装饰器介绍

    """装饰器 定义:本质是函数(器:就是函数的意思),功能:装饰其他函数,就是为其他函数添加附加功能 原则: 1. 不能修改被装饰的函数的源代码 2. 不能修改被装饰的函 ...

  6. 洛谷 P1106 删数问题

    一定要认真审题   “去掉其中任意k个数字后剩下的数字按原左右次序将组成一个新的正整数”   也就是说 输入:7893400   4     输出:300  (00在原顺序中位于3后边) 输入:789 ...

  7. JS3D效果

    <!DOCTYPE html> <html> <head> <title></title> <meta charset="u ...

  8. Java基础再复习(继承、多态、方法内部类**、HashMap用法**、参数传递**)

    ###继承: package com.shiyan; public class Animal { public int legNum; //动物四肢的数量 //类方法 public void bark ...

  9. selenium自动化之鼠标操作

    在做自动化测试的时候,经常会遇到这种情况,某个页面元素,你必须要把鼠标移动到上面才能显示出元素.那么这种情况,我们怎么处理呢?,selenium给我们提供了一个类来处理这类事件——ActionChai ...

  10. zabbix 监控Nginx和PHP

    原理 Nginx和PHP(5.3及以上版本)都自带了一个状态页,默认没有开启,通过开启这个状态页即可获取实时的工作状态. Nginx状态获取 Nginx的配置默认是拒绝通过IP来访问,我们可以再默认虚 ...