EntityFramework Code-First 简易教程(二)-------Code First约定
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)约定是:
- Code-First 包含的类型作为一个DbSet属性被定义在context类中(Code-First includes types defined as a DbSet property in context class.)
- Code-First 包含的引用类型被包含在实体类型中,即使它被定义在不同的集合里(Code-First includes reference types included in entity types even if they are defined in different assembly.)
- 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约定的更多相关文章
- WebGL简易教程(二):向着色器传输数据
目录 1. 概述 2. 示例:绘制一个点(改进版) 1) attribute变量 2) uniform变量 3) varying变量 3. 结果 4. 参考 1. 概述 在上一篇教程<WebGL ...
- Entity Frame Code First 简易教程
简介 什么是ORM 搭建Entity FrameWork CodeFirst应用 数据库迁移 表属性常见配置 Entity FrameWork 一对多.多对多 一.简介 Entity Framewor ...
- PySide 简易教程<二>-------工欲善其事,必先利其器
OK , 在Linux的开发环境下,对于我们的简短的PySide程序而言,不需要使用QtCreator,使用文本编辑器.之所以,使用文本编辑器,是因为小应用代码量很少,更重要的是一行行的写可以加深我们 ...
- Dart 语言简易教程系列
google Fuchsia系统 及 dart语言简介 在 InteIIiJ IDEA 中搭建 Dart 的开发环境 Dart Linux 开发环境搭建 Dart 语言简易教程(一) Dart 语言简 ...
- WebGL简易教程(三):绘制一个三角形(缓冲区对象)
目录 1. 概述 2. 示例:绘制三角形 1) HelloTriangle.html 2) HelloTriangle.js 3) 缓冲区对象 (1) 创建缓冲区对象(gl.createBuffer( ...
- WebGL简易教程(四):颜色
目录 1. 概述 2. 示例:绘制三角形 1) 数据的组织 2) varying变量 3. 结果 4. 理解 1) 图形装配和光栅化 2) 内插过程 5. 参考 1. 概述 在上一篇教程<Web ...
- WebGL简易教程——目录
目录 1. 绪论 2. 目录 3. 资源 1. 绪论 最近研究WebGL,看了<WebGL编程指南>这本书,结合自己的专业知识写的一系列教程.之前在看OpenGL/WebGL的时候总是感觉 ...
- mysql进阶(二)索引简易教程
Mysql索引简易教程 基本概念 索引是指把你设置为索引的字段A的内容储存在一个独立区间S里,里面只有这个字段的内容.在找查这个与这个字段A的内容时会直接从这个独立区间里查找,而不是去到数据表里查找. ...
- Ocelot简易教程(二)之快速开始2
为什么这篇的标题叫"Ocelot简易教程(二)之快速开始2"呢,因为很多朋友跟我说上一篇" Ocelot简易教程(二)之快速开始1"内容太少了,只是简单介绍Oc ...
- Ocelot简易教程(二)之快速开始1
Ocelot简易教程目录 Ocelot简易教程(一)之Ocelot是什么 Ocelot简易教程(二)之快速开始1 Ocelot简易教程(二)之快速开始2 Ocelot简易教程(三)之主要特性及路由详解 ...
随机推荐
- Vue.js基础拾遗
本篇目录: 模版语法 插值 指令 v-bind指令 v-on指令 计算属性与侦听器 计算属性VS方法 计算属性VS侦听属性 Class与Style绑定 绑定HTML Class 绑定内联样式 条件渲染 ...
- async & await 异步编程小示例,一看就懂
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...
- es6学习笔记11--Proxy和Reflect
Proxy概述 Proxy用于修改某些操作的默认行为,等同于在语言层面做出修改,所以属于一种“元编程”(meta programming),即对编程语言进行编程. Proxy可以理解成,在目标对象之前 ...
- pdf.js 使用汇总
https://www.cnblogs.com/iPing9/p/7154753.htmlhttp://blog.csdn.net/m0_38021128/article/details/708684 ...
- elasticsearch6.7 05. Document APIs(2)Index API
Single document APIs Index API Get API Delete API Update API Multi-document APIs Multi Get API Bulk ...
- oracle逐步学习总结之约束(基础五)
原创作品,转自请在文章明显位置注明出处:https://www.cnblogs.com/sunshine5683/p/10167717.html oracle中的约束主要有非空约束(not null) ...
- Java面试题阶段汇总
初级面试题 Java面试题-基础篇一 Java面试题-基础篇二 Java面试题-集合框架篇三 Java面试题-基础篇四 Java面试题-基础篇五 Java面试题-javaweb篇六 Java面试题 ...
- Spring 概念
spring概念 1.spring是一个开源的轻量级的开源框架. 2.spring的核心主要分为两部分: (1)aop:面向切面编程,扩展功能不是修改源代码实现. (2)ioc:控制反转,比如有一个类 ...
- [翻译]C# BAD PRACTICES: Learn how to make a good code by bad example---C#:如何将坏的代码重新编译为好的代码
自己的前言说明: 本文原作者:Radoslaw Sadowski,原文链接为:C# BAD PRACTICES: Learn how to make a good code by bad exampl ...
- CSS十大选择器
CSS十大选择器: 1.id选择器 # 2.class选择器 句号 . 3.标签选择器 标签名称 4.相邻选择器 加号 + 5.后代选择器 空格 6.子元素选择器 大于号 > 7.多元素 ...