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框架分类:
DataObjects.Net
NHibernate
OpenAccess
SubSonic
请注意: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实体。