一、前言
本文将详细介绍Entity Framework(EF)框架的基本概念、核心组件以及它提供的几种主要数据访问方式。
1、Entity Framework概要
Entity Framework是微软以ADO.NET为基础所发展出来的对象关系映射(O/R Mapping)解决方案。该框架曾经为.NET Framework的一部分,但Version 6之后从.NET Framework分离出来,可通过NuGet获取。
Entity Framework利用抽象化数据结构的方式,将每个数据库对象都转换成应用程序对象 (Entity),而数据字段都转换为属性 (Property),关系则转换为结合属性 (Association),让数据库的E/R(实体-联系图)模型完全的转成对象模型,让程序设计师能用最熟悉的编程语言来调用访问。
2、什么是ORM
对象-关系映射(Object Relational Mapping,简称ORM),用来把对象模型表示的对象映射到基于SQL的关系模型数据库结构中去。这样在具体的操作实体对象的时候,就不需要再去和复杂的SQL语句打交道,只需简单的操作实体对象的属性和方法。即用操作对象的方式来操作数据库。
其它ORM框架:Dapper、NHibernate等。
3、Entity Framework使用说明
①、EF是建立在ADO.NET框架之上的,底层使用的是ADO.NET方法和类来执行数据操作,具体如下图所示:
②、EF支持SQL Server、MySQL、Oracle等主流数据库。
③、EF采用约定大于配置的框架原则,能遵守约定就不要去配置。
④、EF开发数据库的两种形式先建数据库或者先建模型。
⑤、EF三种开发模式:
◆ DataBase First (数据库优先)
如果数据库已存在,可以使用VS自动生成数据模型以及相关的edmx文件。
使用简单、方便,适用于数据库会频繁修改来满足新的需求。会出现修改了数据库在程序中更新EF不起作用等问题。
◆ Model First (模型优先)
如果数据库未创建,可以在VS中利用Model设计数据库,通过设计器生成映射信息(edmx文件),并生成数据库。开发中很少使用。
◆ Code First (代码优先)(*)
可以通过设计的数据模型自动生成数据库,也可以通过已存在的数据库生成数据模型,进行数据库映射,都没有edmx文件。
完全控制代码,即没有自动生成的模型和上下文代码。
数据库由EF帮助生成,当修改模型后,EF使用DB Miguration自动帮助修改数据库,但也可以禁用Miguration,手动创建(推荐)。
上图中前三种分别是DataBase First、Model First 和Code First,而第四种也是Code First。
那么第三个和第四个到底有什么区别?项目中如何使用?下面将会重点讲解。(*)
⑥、EF三种开发模式使用比较,如下图所示:
二、Entity Framework 访问数据三种方式
1、DataBase First模式
1.1、创建
①、创建一个应用程序选择(.NET Framework类库),选择“添加” ->“新建项”->点击“数据”->选择“ADO.NET 实体数据模型”,具体如下图所示:
②、选择模型内容来自“数据库的EF设计器”,具体如下图所示:
③、点击新建连接如图二所示,选择数据库地址、连接方式和数据库,然后配置数据连接字符串如图一所示,具体如下图所示:
④、选择要映射的“PersonInfo”表,具体如下图所示:
⑤、创建完模型之后,你会发现Visual Studio自动生成了“Person”实体类和一个“EntityModelContext”数据库上下文操作类,具体如下图所示:
1.2、应用
查询数据,创建控制台应用程序,通过NuGet包管理器,添加“Entity Framework”引用,然后配置相应的App.config的数据库连接,创建测试代码:
static void Main(string[] args)
{
//实例化数据库上下文
using (var dbContext=new DemoDBEntities() )
{
//使用Lambda表达式查询数据
var info = dbContext.PersonInfo.Where(i => i.Name == "ZhangSan").ToList();
//使用Linq语句查询
var info1 = from i in dbContext.PersonInfo
where i.ID == 1
select i;
//获取查询结果
foreach (var item in info)
{
Console.WriteLine(" Lambda方式的查询结果:姓名:" + item.Name +" 年龄:"+item.Age);
}
//foreach (var item in info1)
//{
// Console.WriteLine(" Linq 方式的查询结果:姓名:" + item.Name + " 年龄:" + item.Age);
//}
Console.ReadLine();
}
}
结果如下图所示:
1.3、说明
Database First是以数据库为中心的开发方式;
使用这种模式必须要先设计和创建数据库,然后使用VS在已有数据库的基础上创建ADO.NET实体数据模型,然后使用EF访问和操作数据库;
如果数据库表结构发生改变后,只需在模型设计视图空白处右键,选择“从数据库更新模型”接着按照向导操作即可完成模型更新;
上面只是演示了一个查询的小功能,EF的强大机制还需动手实践和操作。
2、Model First模式
2.1、创建
①、创建一个应用程序选择(.NET Framework类库),选择“添加” ->“新建项”->点击“数据”->选择“ADO.NET 实体数据模型”,具体如下图所示:
②、选择模型内容来自“空EF设计器模型”,具体如下图所示:
③、开始设计实体,在空白处右击,添加实体(UserInfo)和实体的属性(eg:ID、Name、Age)等 ,具体如下图所示:
④、实体模型设计完成,接下来要生成数据库,选择“根据模型生成数据库”,具体如下图所示:
⑤、创建数据库,填写相应的数据库连接属性,具体如下图所示:
⑥、EF模型选择和Visual Studio自动生成DDL文件,具体如下图所示:
⑦、选择自动创建的SQL脚本,此时数据已生成,执行脚本生成所需要的表,具体如下图所示:
⑧、打开数据库,可以看到创建的数据库以及表,具体如下图所示:
2.2、应用
查询数据,创建控制台应用程序,通过NuGet包管理器,添加“Entity Framework”引用,然后配置相应的App.config的数据库连接,创建测试代码:
static void Main(string[] args)
{
using (var dbContext = new ModelFirstContainer())
{
//添加
UserInfo userModel = new UserInfo();
userModel.Name = "WangWu";
userModel.Age = 18;
dbContext.UserInfo.Add(userModel);
dbContext.SaveChanges();
//Linq查询
var list = from i in dbContext.UserInfo
where i.Name == "ZhangSan"
select i;
//Lambda 表达式查询
var info = dbContext.UserInfo.Where(i => i.Name == "ZhangSan").ToList();
//获取数据
foreach (var item in list)
{
Console.WriteLine(" Linq 方式的查询结果:姓名:" + item.Name + " 年龄:" + item.Age);
}
foreach (var item in info)
{
Console.WriteLine(" Lambda方式的查询结果:姓名:" + item.Name + " 年龄:" + item.Age);
}
Console.ReadLine();
}
}
结果如下图所示:
2.3、说明
ModelFirst模式是实体模型先行的开发方式;
先设计实体,然后根据实体再去生成数据库并且进行相应的操作;
使用这种方式的唯一原因就是想体验视觉实体设计器。
3、Code First模式
文章开始说到的Code First模式有两种选择一种是“空CodeFirst模型”,另一种是“来自数据库的CodeFirst”,具体如下图所示:
上图分别对两种模式进行了描述,那它们到底该如何使用以及区别是什么?请看下面的例子。
3.1、空Code First模式
1、创建
①、创建一个应用程序选择(.NET Framework类库),选择“添加” ->“新建项”->点击“数据”->选择“ADO.NET 实体数据模型”,具体如下图所示:
②、选择模型内容来自“空Code First模型”,具体如下图所示:
③、点击完成,具体如下图所示:
通过上图我们可以看到生成相应的数据库上下文以及数据库连接字符串。(可以根据自己的需求进行修改配置以及添加对应的实体)
2、应用
1)、连接配置文件(修改数据库连接字符串,改成我们要存放数据库服务器名)
<connectionStrings>
<add name="CodeDB" connectionString="data source=.;initial catalog=CodeDB;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework"
providerName="System.Data.SqlClient" />
</connectionStrings>
2)、代码示例:
static void Main(string[] args)
{
using (var dbContext=new CodeDB() )
{
UserInfo userModel = new UserInfo();
userModel.Name = "ZhangSan";
dbContext.UserInfo.Add(userModel);
dbContext.SaveChanges();
Console.ReadKey();
}
}
3)、运行上面代码,“空Code First模型”,生成的数据库如下图所示:
从上图可以看出:
1、自动生成数据库CodeDB;
2、数据库中生成一张叫__MigrationHistory 的表(是用于记录代码迁移的历史记录,也是代码迁移模式的开关,后面会聊);
3、数据库中还创建一张实体类型(UserInfoes的表),包括字段名以及字段类型等信息;
4、利用代码添加一条数据到UserInfoes的表中。
以上就是通过空Code First模式创建的数据库以及表(通过代码实现数据的创建以及表添加)上面的示例操作到这一步都显示正常,但是我们在实际开发中,
有时需要向数据库中添加表以及修改表字段和属性,那现在我们在实体的代码中添加一个Age字段,具体如下所示:
public class UserInfo
{
public int Id {
get; set; }
public string Name {
get; set; }
//实体中添加Age字段
public string Age {
get; set; }
}
现在运行程序
程序出现异常,那我们来看看什么意思“从数据库创建以来支持CODEDB上下文的模型发生了变化,考虑使用代码第一迁移来更新数据库”,
说的就是模型与实际数据库结构不一致,需要使用 Code First 中的数据迁移功能来解决问题,下面我们就来看看数据迁移。
3、数据迁移的用法
1、什么情况需要进行数据迁移
在开发中使用空Code First模式,如果涉及到数据表的变更以及字段修改等操作,该如何做呢?当然如果是新项目,删除数据库,然后重新生成就行了,
那么如果是线上的项目,数据库中已经有数据了,那么删除数据库重新生成就不行了,那么该如何解决呢?EF Code First提供了一种数据迁移的操作。
2、如何进行数据迁移
● 手动迁移
当模型与实际数据库结构不一致时,就需要使用数据迁移。数据迁移我们需要掌握三个方法,它们分别是:
1) 在当前项目中启用数据迁移 Enable-Migrations
2) 添加迁移版本 Add-Migration 版本名称
3) 更新数据库 Update-Database
第一步,选择需要启用数据迁移的项目,打开“视图”->“其它窗口”->“程序包管理器控制台” 或者可以按快捷键 Alt+V,E,O,然后输入命令:Enable-Migrations,具体如下图所示:
显示当前项目中已启用数据迁移,项目中会多出 Migrations文件夹以及相关代码(Migrations文件夹主要是数据迁移的信息),具体如下图所示
第二步由于我们的模型已经发生了改变,所以需要添加一个新的迁移版本,在程序包管理控制台
执行如下命令:Add-Migration v1.0 ( 其中的v1.0表示版本号,名称可以自定义),此时再看项目中就会多出一个文件:
第三步通过数据迁移代码可以看到数据库是如何进行更新和修改,想要让数据库发生改变,为表添加一个Age字段,
还是需要用到第三个命令:Update-Database(执行成功之后,表中就会添加一个 Age字段)
完成以上三个步骤,此时的模型与实际数据库结构已经一致,再运行程序,程序就不会报错了。
● 自动迁移
上面我们利用命令方式手动完成数据迁移的,那么如果我们在实际开发中,每次修改完模型都要这样更新数据库吗?如果表中有数据时,是否会丢失数据?
当然还有一种方式自动迁移,我们需要在项目中启用Migrations,然后在Configuration类中设置AutomaticMigrationsEnabled设置为true
还需要在DbContext构造函数中写上这句
Database.SetInitializer(new MigrateDatabaseToLatestVersion("DBConnectionString")),
通过构造函数把数据库更新为最新,具体如下图所示:
说明:如果不喜欢自动迁移,可以手工完成这个操作。手工迁移的好处后,可以随时退回到某个指定的迁移版本。迁移文件也可以进行版本管理有利于团队开发。
通过使用Code First模式创建出来的数据库,默认是开启了数据迁移,如果我们模型进行了修改,那么就需要在项目中开启数据迁移,进行模型和数据库同步。
数据迁移有分为手动迁移和自动迁移,上面已讲解,可以根据自己的项目需求进行选择。
但是在实际开发中进行数据迁移难免会出现一些问题,如果数据库存有大量数据,迁移过程有可能导致数据丢失,每次更新模型都要进行数据迁移,
给我们开发带来很多不便,但是还是想用代码先行模式开发,那么我就可以使用“来自数据库的Code First”的方式,默认是关闭数据迁移的,
方便我们随时修改数据库以及模型,提高开发效率,推荐使用,请看下面讲解。
3.2、来自数据库的Code First
1、场景
◆ 数据库已存在并且不想启用数据库迁移;
◆ 习惯通过手动修改实体类,手动修改数据库表结构,来同步数据库和模型;
◆ 实现代用优先原则。
2、创建
①、创建一个应用程序选择(.NET Framework类库),选择“添加” ->“新建项”->点击“数据”->选择“ADO.NET 实体数据模型”,具体如下图所示:
②、选择模型内容来自“来自数据库的Code First”,具体如下图所示:
③、选择连接建据库,填写相应的数据库连接属性,具体如下图所示:
④、选择需要的数据库对象,具体如下图所示:
⑤、点击完成,项目中生成相应的数据库上下文,具体如下图所示:
3、应用
static void Main(string[] args)
{
using (var dbContext=new CodeEntity() )
{
PersonInfo userModel = new PersonInfo();
userModel.Name = "LiSi";
dbContext.PersonInfo.Add(userModel);
dbContext.SaveChanges();
Console.ReadKey();
}
}
4、说明
通过上面的示例代码运行我们可以看到,“来自数据库的Code First”,我们可以通过手动创建数据库,手动修改实体,方便我们随时修改数据库和实体,而且还不会生成__MigrationHistory 的表,也不用进行数据迁移,这种方式可以更好地提现Code First的好处。
3.3 、Code First 模式总结
1)Code First模式中,当模型与表结构不一致时,程序会报错,有两种方式使模型和表结构一致,一种是手动修改模型代码和表结构,另一种是使用数据迁移功能。
这两种方式不是想选哪一个就选哪一个,取决于是否使用了数据迁移 。
2)使用空Code First模型创建的数据库默认是开启数据迁移的;
3)使用来自数据库的Code First模式中的数据库,默认是关闭数据迁移的。
4)使用来自数据库的Code First模式,通过手动改写实体类,手动改数据库表结构,来同步模型与实际表结构,可以完全自己控制代码,推荐使用。
三、Entity Framework 总结
Database First:用于数据库已经存在,可以使用VS自动生成数据模型,已经相关的edmx信息。
Model First:数据库未创建,可以在VS中利用Model设计数据库,通过设计器生成映射信息(edmx文件),并自动生成数据库。
Code First:通过设计的数据模型自动生成数据库,不需要额外edmx文件,也可通过已存在的数据库生成数据模型,进行数据库映射,同样不需要edmx文件。
Entity Framework为.NET开发提供了多种数据访问方式,每种方式都有其独特的优点和适用场景。在选择数据访问方式时,应根据应用的具体需求、性能要求以及团队的技术栈来做出决策。通过深入了解这些方式,并结合实际项目经验,可以更加高效地使用Entity Framework来构建数据访问层。