Entity Framework框架

EF版本

EF版本

相关版本特性介绍

EF3.5

基于数据库优先的模式的基础ORM框架(Basic O/RM support with Database First approach.)

EF4.0

支持简单传统CLR对象(Plain old CLR Object),懒加载, 提高了可测试性,可以自定义代码的生成,支持ModeFirst; (POCO Support, Lazy loading, testability improvements, customizable code generation and the Model First approach.)

注意:POCO是指Plain Old Class Object,也就是最基本的CLR Class,在原先的EF中,实体类通常是从一个基类继承下来的,而且带有大量的属性描述。而POCO则是指最原始的Class,换句话说这个实体的Class仅仅需要从Object继承即可,不需要从某一个特定的基类继承。主要是配合Code First使用。Cost Frist则是指我们先定义POCO这样的实体class,然后生成数据库。实际上现在也可以使用Entity Framework Power tools将已经存在的数据库反向生成POCO的class(不通过edmx文件)。

EF4.1

第一次可以在NuGet里面下载EF框架,简单的数据上下文接口支持,EF4.1.1补丁发布,以及修复EF4.1中的Bug,当然还有Code -First代码先行。 (First to available in the NuGet, Simplified DBContext API over ObjectContext, Code First approach. EF 4.1.1 patch released with bug fixing of 4.1.)

EF4.3

Code First 迁移特性允许使用Code-First方式生成的数据库,根据你的Code-First实体变化而向上迁移,EF4.3.1补丁发布以修复EF4.3的Bug

(Code First Migrations feature that allows a database created by Code First to be incrementally changed as your Code First model evolves. EF 4.3.1 patch released with bug fixing of EF 4.3.)

EF5.0

宣布EF开源,支持枚举,表值函数,空间数据类型,多个图表模型,图形化设计界面,引入存储过程,EF Power工具以及各种性能的改进;

(Announced EF as Open Source. Introduced Enum support, table-valued functions, spatial data types, multiple-diagrams per model, coloring of shapes on the design surface and batch import of stored procedures, EF Power Tools and various performance improvements.)

EF 6.0 - Current release

EF 6.0/EF 6.1是Entity Framework最新发布的版本。包含了很多与Code First相关的新特性,如EF设计器,异步查询,异步保存,弹性连接,依赖解决,等等。。。

(EF 6.0/6.1 is the latest release of Entity Framework. It includes many new features related to Code First & EF designer like asynchronous query & save, connection Resiliency, dependency resolution etc.)

什么是O/RM?

ORM是一个工具,它可以自动的存储数据库(比如MS SQL Server)中领域对象中的数据,而不需要很多编程。

O/RM包含3个主要的部分:

           1.领域类对象

     2.关系数据库对象

           3.映射信息(领域对象,怎样映射到数据库对象【表,视图,存储过程】?)

     ORM允许我们把数据库设计和领域类设计分开来,这样保证了程序的可维护性和可扩展性,ORM同样自动帮助我们生成了增删查改(CURD)操作,所以我们不必手动去写了。

 

     

Tips:要了解更多的ORM技术,可以访问 这个链接: Object-relational Mapping

ORM框架分类:

  1. DataObjects.Net

  2. NHibernate

  3. OpenAccess

  4. SubSonic 

  5. 请注意:EF是微软的开源ORM框架

EF的框架设计

EDM(Entity Data Model)【实体数据模型】:实体数据模型包含三个主要部分:概念模型,映射,存储模型;

Conceptual Model【概念模型】:包含模型类和类之间的关系。概念模型是独立于数据库设计的;

Storage Model【存储模型】:存储模型是数据库设计的实体,它包含数据表,视图,存储过程,还有他们之间的关系和键值;

Mapping【映射】:映射包含这个概念模型怎么映射到存储模型的信息;

LINQ to Entities:LINQ to Entities是查询语言,用来查询对象模型。它返回的是定义在概念模型中的实体;

Entity SQL:Entity SQL是另外的查询语言,就像LINQ to Entities一样,然而它和LINQ to Entities有一点不同,我们需要单独去学一下;

Object Service:Object Service是一个主要的切入点去从数据库中获取数据,并返回数据。Object Service负责将数据返回给Entity Client Data Provider实体对象结构;

Entity Client Data Provider:它主要的职责是将L2E(LINQ to Entity)或者Entity SQL查询语言,拼接成底层数据库可以理解的语言。它负责和ADO.NET Data Provider通信;

ADO.NET Data Provider:这个层,主要是用标准的ADO.NET和数据库打交道。

安装Entity Framework【Setup Entity Framework Environment

Entity Framework 5.0 API是分布在两个地方:NuGet和.NET Framework中,这个.NET framework 4.0/4.5包含EF核心的API,然而通过NuGet包获取的EntityFramework.dll包含EF 5.0特别的特性;EF6.0中不是分开的:

在这个基础的系列课程中,我将会使用EF 6.0,这个最新的EF版本来学习,

学习EF,首先要安装下面的工具:

.NET Framework 4.5

Visual Studio 2012/2013/2015

MS SQL Server2005/2008/2012/2014 Express

下面我们来看看怎么安装EF吧:

我们打开VS2012新建项目:

然后,我们选中“项目名称”,点击右键,选择“管理Nuget程序包”,在弹出来的界面中,输入:"EntityFramework",会自动查询到EntityFramework,然后点击安装,按照我下面的图示进行就可以了:

安装完成之后,是这样的:然后关闭这个窗口就行了。。。

 

创建数据库:

这个系列课程中,我将会使用SchoolDB样例数据库,它包含数据表,存储过程,和视图;数据库的设计如下:

 

在这个数据图表中,我们可以看到,不同表之间的关系:

  • 一对一: Student and StudentAddress表之间是一对一的关系,例如一个Student有0到1个的StudentAddress;

  • 一对多: Standard and Teacher表之间是一对多的关系,例如很多Teacher关联一个Standard;

  • 多对多: Student and Course表之间是多对多关系,通过中间表StudentCourse 联系在一起,例如;一个学生可以选择很多课程,同时一个课程可以有很多学生来选择;

Download Sample Project for all the tutorials on entity framework.

 

好了,EF的安装就到此,相信大家已经学会了,后面一节我将要学习一个简单的实体数据模型来创建数据库。

数据库一对一,一对多,多对多关系

关联映射:一对多/多对一

存在最普遍的映射关系,简单来讲就如球员与球队的关系;

一对多:从球队角度来说一个球队拥有多个球员 即为一对多

多对一:从球员角度来说多个球员属于一个球队 即为多对一

数据表间一对多关系如下图:

 

 

 

 

 

关联映射:一对一

一对一关系就如球队与球队所在地址之间的关系,一支球队仅有一个地址,而一个地址区也仅有一支球队。

数据表间一对一关系的表现有两种,一种是外键关联,一种是主键关联。图示如下:

一对一外键关联:

 

 

一对一主键关联:要求两个表的主键必须完全一致,通过两个表的主键建立关联关系

 

 

 

 

关联映射:多对多

多对多关系也很常见,例如学生与选修课之间的关系,一个学生可以选择多门选修课,而每个选修课又可以被多名学生选择。

数据库中的多对多关联关系一般需采用中间表的方式处理,将多对多转化为两个一对多。

数据表间多对多关系如下图:

 

创建实体数据模型【Create Entity Data Model

现在我要来为上面一节末尾给出的数据库(SchoolDB)创建实体数据模型;

SchoolDB数据库的脚本我已经写好了,如下:

USE master
GO 
IF EXISTS(SELECT * FROM sys.sysdatabases WHERE name='SchoolDB')
DROP DATABASE SchoolDB;
GO 
CREATE DATABASE SchoolDB
GO 
USE SchoolDB;

GO --创建Standard表
IF EXISTS (SELECT * FROM sysobjects WHERE name='Standard')
DROP TABLE [Standard];
GO 
CREATE TABLE  [Standard]
(
StandardID INT PRIMARY KEY ,
StandardName NVARCHAR(50),
[Description] NVARCHAR(250)
);
 
GO 

--创建Student表
IF EXISTS (SELECT * FROM sysobjects WHERE name='Student')
DROP TABLE Student;
GO 
CREATE TABLE  Student
(
StudentID INT PRIMARY KEY,
StudentName NVARCHAR(100) NOT NULL,
StandardID INT  REFERENCES [Standard](StandardID),
[RowVersion] NVARCHAR(50)

);

GO 

--创建StudentAddress表
IF EXISTS (SELECT * FROM sysobjects WHERE name='StudentAddress')
DROP TABLE StudentAddress;
GO 
CREATE TABLE  StudentAddress
(
StudentID INT PRIMARY KEY,
Address1 NVARCHAR(100) ,
Address2 NVARCHAR(100), 
City NVARCHAR(100),
[State] NVARCHAR(100),
CONSTRAINT StudentID_FK FOREIGN KEY(StudentID) REFERENCES dbo.Student(StudentID)
);

GO 

--创建Teacher表
IF EXISTS (SELECT * FROM sysobjects WHERE name='Teacher')
DROP TABLE Teacher;
GO 
CREATE TABLE  Teacher
(
TeacherID INT PRIMARY KEY ,
TeacherName NVARCHAR(50),
StandardID INT  REFERENCES [Standard](StandardID),
TeacherType NVARCHAR (100)

);
GO 


--创建Course表
IF EXISTS (SELECT * FROM sysobjects WHERE name='Course')
DROP TABLE Course;
GO 
CREATE TABLE  Course
(
CourseID INT PRIMARY KEY ,
CourseName NVARCHAR(50),
Location NVARCHAR(500),
TeacherID INT REFERENCES dbo.Teacher(TeacherID)

);

GO 


--创建StudentCourse表
IF EXISTS (SELECT * FROM sysobjects WHERE name='StudentCourse')
DROP TABLE StudentCourse;
GO 
CREATE TABLE  StudentCourse
(
StudentID INT  REFERENCES Student(StudentID),
CourseID INT  REFERENCES dbo.Course(CourseID),
CONSTRAINT StudentID_CourseID PRIMARY KEY(StudentID,CourseID),

);

GO 

首先我们打开上面一节创建的项目,选中“项目名称”,右键选择”属性“,我们要确保使用的.NET framework版本是4.5;

接下来,就是创建实体数据模型了:选中项目名称:

 

 

 

现在我们以XML编译器的方式打开EDMX文件看看:

 

EF中的实体类型

EF中有两种类型的实体:POCO Entity和dynamic proxy entity。

POCO class是一个类,它不依赖任何.NET framework的基类,它就像任何其他的普通类一样,这也是为什么被称之为“Plain Old CLR Object”的原因;

这些由实体数据模型生成的POCO实体支持大多数的增删查改的功能。下面是一个Studnet POCO实体:

public classStudent
        {publicStudent()
            {this.Courses = new List<Course>();
            }public int StudentID { getset; }public string StudentName { getset; }public Nullable<intStandardId { getset; }public Standard Standard { getset; }public StudentAddress StudentAddress { getset; }public IList<Course> Courses { getset; }
        }

动态代理是POCO实体运行状态下的代理类,它就像POCO实体的包装类,动态包装实体支持懒加载,自动跟踪改变的特性;

一个POCO实体需要满足下面的条件,才可以成为POCO代理

1.必须定义成Public

2.不能是密封的

3.不能是抽象的;

4.导航属性必须定义成public virtual;

5.每个集合属性必须是Icollection<T>;

6.在context类中,ProxyCreationEnabled 这个选项必须不能是false(默认是true);

下面的POCO Student实体满足了上面的条件,它将会在运行的时候成为动态代理实体;

public classStudent
        {publicStudent()
            {this.Courses = new HashSet<Course>();
            }public int StudentID { getset; }public string StudentName { getset; }public Nullable<intStandardId { getset; }public virtual Standard Standard { getset; }public virtual StudentAddress StudentAddress { getset; }public virtual ICollection<Course> Courses { getset; }
        }
注意:动态代理默认是对每个实体都是有效的,然而你可以手动禁止动态代理,通过在上下文类中设置

ProxyCreationEnabled 这个选项为false,而达到目的;

在运行的时候Student POCO实体就会变成代理类:

代理类有两个属性,一个标量属性,一个是导航属性,

标量属性实际值包含在实体中,例如Student实体有标量属性StudentID和StudentName,这和数据库中字段一致;

导航属性指向另外相关联的实体,Student实体有一个Standard属性作为导航属性,可以保证程序从一个Student导航到相关联的standard实体。

参见

【Basics of Entity Framework】【EF基础系列1】