EF简介
ORM的概念
对象关系映射Object Relation Mapping ,通俗说:用操作对象的方式来操作数据库。是一种程序技术,用于实现面向对象编程语言里不同类型关系数据之间的转换,从效果上说,它其实是创造了一个可在编程语言中使用的“虚拟对象数据库”
关于使用服务端语言操作数据库-ADO.NET技术,ADO.NET技术学习程序分层时学习过Model层,而这里的模型层指的是在服务端编程语言中用来映射数据库中数据模型的一个对象映射。
而在ORM技术而言,可以理解为ORM主要是为了更方便快速的实现ADO.NET技术
ORM技术的优势
- 首先在学习编程中,最终都要学习的是访问数据库,而在C#语言中使用C#语言访问数据库技术是微软提供的ADO.NET技术
- 因此在做程序编程时,只要有关数据库的操作,我们总结出来一套经验:先写DBHelper,然后创建目标数据库中的数据对象模型,这个步骤很麻烦,但是又不得不写
- 实现更加方便快捷的开发,方便数据库移植
.NET中的ORM框架
- NHibernate
- MyBatis.NET
- LinQ to SQL(已经不使用)
- ADO.NET Entity Framework
EF的本质
EF底层仍然是对ADO.Net的封装。EF支持SQLServer、MYSQL、Oracle、Sqlite等所有主流数据库。
Object Services
它是Entity Framework提供的一系列操作业务对象的API。这些API都依赖Entity Client实现对数据库的访问
EDM实体数据模型
- 作用:将关系数据库模型映射为实体数据模型,由三部分组成,存放在一个扩展名为.edmx的XML文件中
- SSDL:负责与数据库中的数据表做实体对应(就是将数据库中数据表结构和关系用XML文件描述)
- MSL:将存储模型中的字段和概念模型中的属性对应
- CSDL:概念模型对应的实体类,用实体类表示数据库中的对象
Entity Client实体代理
- 概念:Entity Framework实现了一套类似于ADO.NET中的数据库操作类,这些操作类称之为Entity Client
- 作用:用来操作EMD实体数据模型
ADO.NET Provider
- 作用:翻译成SQL语句,用来访问数据库
- 说明:Entity Framework是ADO.NET的一个技术子集
Entity Client和ADO.NET
- ADO.NET的连接类是向数据库发送SQL命令操作表或试图,Entity Client是向EDM发送Entity SQL
- Entity Client通过Entity Connection、Entity Command等类进行模拟ADO.NET,有自己的SQL语句
- Entity Client将查询转交给数据库提供者ADO.NET Provider,并由数据库提供者翻译为SQL语句
EF应用程序有以下优点
- 应用程序可以通过更加以应用程序为中心的概念性模型(包括具有继承性、复杂成员和关系的类型)来工作。
- 应用程序不再对特定的数据引擎或存储架构具有硬编码依赖性。
- 可以在不更改应用程序代码的情况下更改概念性模型与特定于存储的架构之间的映射。
- 开发人员可以使用可映射到各种存储架构(可能在不同的数据库管理系统中实现)的一致的应用程序对象模型。
- 多个概念性模型可以映射到同一个存储架构。
- 语言集成查询支持可为查询提供针对概念性模型的编译时语法验证。
EF框架的搭建
EF的创建
使用EF进行数据库开发的时候有两个东西建:建数据库(T_Persons),建模型类(Person)。EF的三种创建方法:
- DataBase First(数据库优先):先创建数据库表,然后自动生成EDM文件,EDM文件生成模型类。简单展示一下DataBase First 的使用。
- Model First(模型优先):先创建Edm文件,Edm文件自动生成模型类和数据库;
- Code First(代码优先):程序员自己写模型类,然后自动生成数据库。没有Edm。
三种创建的区别
- DataBase First 简单、方便,但是当项目大了之后会非常痛苦;
- Code First 入门门槛高,但是适合于大项目。
- Model First…… (不需要考虑)
无论哪种First,一旦创建好了数据库、模型类之后,后面的用法都是一样的。业界都是推荐使用Code First,新版的EF中只支持Code First,因此我们这里只讲Code First。
DataBase First
- 首先在数据库中创建好数据库、数据表,以及表结构
- 在创建C#项目时,添加EF框架,选择“ADO.NET 实体数据模型”
- 在实体数据模型向导中选择“来自数据库的EF设计器”
- 进行数据库连接中“建立新的连接”
- 进行寻找连接目标数据库,创建EF数据实体模型
- App.config:配置文件,里面有连接数据库字符串,EF的相关配置
- StudentModel.edmx:EDM元数据文件
- StudentModel.Context.cs:数据库上下文类,可以理解为是映射关系类
- StudentMode.tt:实体类集合
EDM元数据
EDM设计器模式和XML结构
XML结构中明显有三个类型节点,分别对应EDM中的存储模型、概念模型、映射
实体文件
在StudentMode.tt文件里面,可以找到实体文件和选择的数据库表的对应实体表
数据库上下文类
namespace DBFirst { using System; using System.Data.Entity; using System.Data.Entity.Infrastructure;
public partial class StudentManagerEntities : DbContext { public StudentManagerEntities() : base("name=StudentManagerEntities") { } protected override void OnModelCreating(DbModelBuilder modelBuilder) { throw new UnintentionalCodeFirstException(); } public virtual DbSet<Admin> Admin { get; set; } public virtual DbSet<Course> Course { get; set; } public virtual DbSet<Score> Score { get; set; } public virtual DbSet<Student> Student { get; set; } }
}
StudentModel.Context.cs集成自DbContext
DbContext-实体对象容器
作用:操作数据库的工具,负责管理对象的CRUD(增、删、改、查)操作,以及相应的事务及并发问题
特别注意:某个数据表的字段全部都是外键的时候,不会生成该表对应的实体类
使用EF查询单表数据
在DbSet< T>对象中查询符合条件的实体,一般用基类IEnumerable< Student>类型包含的两个方法
IQueryable<Student> Where<Student>(Expression<Func<Student,bool>> predicate)
Student SingleOrDefault<Student>(Expression<Func<Student,bool>> predicate)
private void Form1_Load(object sender, EventArgs e)
{
StudentManagerEntities studentEF = new StudentManagerEntities();
List<Student> list = studentEF.Student.ToList();
}
使用EF实现CRUD
-
添加数据
使用DbSet< T>中的Add方法
然后使用DbContext的SaveChanges()方法
Student stu = new Student() { SName=txtName.Text.Trim(), SAge=int.Parse(txtAge.Text.Trim()),SEmail=txtEmail.Text.Trim(), SSex=radioButton1.Checked?"男":"女" }; studentEF.Student.Add(stu);//只是将实体对象添加到了数据库上下文对应的对象集合中,而并非添加到了数据库中了 int res = studentEF.SaveChanges();//将数据库上下文中的更改保存到数据库中
-
修改数据
从DbContext中获取实体
修改数据
使用DbContext的SavaChanges()方法
if (radioButton1.Checked) { currentStu.SSex = "男"; } else if (radioButton2.Checked) { currentStu.SSex = "女"; } currentStu.SName = txtName.Text.Trim(); currentStu.SAge = int.Parse(txtAge.Text.Trim()); currentStu.SEmail = txtEmail.Text.Trim(); int res = entities.SaveChanges(); this.Close();
-
使用EF删除
使用DbContext获取实体
使用DbSet< T>的Remove()方法
使用DbContext的SaveChanges()方法
Student stu = studentEF.Student.Find(int.Parse(dataGridView1.SelectedRows[0].Cells["Id"].Value.ToString())); if (stu!=null) { studentEF.Student.Remove(stu); studentEF.SaveChanges(); RefreshStudent(); }
Code First
Code First的微软的推荐用法是程序员只写模型类,数据库由EF 帮我们生成,当修改模型类之后,EF 使用“DB Migration”自动帮我们更改数据库。但是这种做法太激进,不适合很多大项目的开发流程和优化,只适合于项目的初始开发阶段。Java的Hibernate 中也有类似的DDL To SQL 技术,但是也是用的较少。“DB Migration”也不利于理解EF,因此在初学阶段,我们将会禁用“DB Migration”,采用更实际的“手动建数据库和模型类”的方式。