第3 章 模型和数据操作 本章导读: MVC的第一个字母M 是Model,它承载着View 层和Controller之间的数据传输, 是数据传输的载体,通过Model层解耦了视图和控制器。MVC框架中Model的主要关 注点是如何把请求的数据自动装配成Action所需要的实体类,除此之外,框架Model层 还可以提供复合实体类自动装配、输入校验、本地化及国际化、字符集编码转换、多重输出 等功能。 在本书中,数据操作是通过EntityFramework(以下简称EF)完成的。EF是微软在 ADO.NET开发以来十分重要的数据访问框架,它不但提供了标准的数据连接自动管理, 也提供了对象关系映射的能力,简化程序员在编写数据访问程序时所需要的SQL指令编 写工作,以及将查询结果转换成强类型对象的需求。随着EF不断进步,它也提供了在部 署数据库时的辅助功能。 本章要点: 本章首先介绍Model的概念,然后介绍ORM 和EF框架的概念,并对EF框架的3 种模型进行详细的讲解,当数据库在使用的过程中需要对数据库中的表结构进行修改时, 则需要使用数据库迁移完成。 首先在项目实践部分使用EF框架中的CodeFirst方式导入现有数据库,然后创建 图书销售系统其他数据模型,这些类在ASP.NET MVC应用程序中扮演Model的角色, 最后使用数据迁移功能同步到数据库中。 3.1 Model的概念 Model,即“模型”,也就是程序中的“数据”。程序是由数据和算法组成的,在MVC应 用程序中,算法由Controller提供,而数据由Model提供。但是,Model并不指程序内的 局部变量、全局变量或常数,而是指由程序外部所提供的数据。程序外部的数据有很多 种,凡是数据库、文件、WebService(网页服务)、其他的应用程序或系统,乃至于由不同 程序所演算出来的结果等,都算是Model。所以,Model并不仅是来自数据库的数据,也 包括来自外部系统或文件的数据。 Model本身基本上并不属于哪个应用程序项目,在大中型应用系统的设计上,Model 并不只归属于某一个应用程序,而是会特别将Model剥离到架构层面上,让Model可以 被大部分应用程序所共享,并且在Model和实际数据源之间插入一个中介层,由这个中 第 3 章 模型和数据操作 27 介层负责与数据源进行互动,包括所熟知的CRUD 动作。如此一来,上层应用程序只需 在关注Model操作的情况下访问Model,而不必担心数据源的数据管理与读写方式,这种 架构在具有弹性与模块化的应用程序中相当常见。 在ASP.NETMVC 应用程序中,Model通常会放在项目的Models文件夹内,以便和 其他程序进行区分,这是基于ASP.约定优于配置” NETMVC 应用程序所强调的“ 原则, 这个原则适合小型应用程序。若一开始就知道要开发的是大型应用程序,Models文件夹 就不适合放系统层次的Model对象,而只能放针对应用程序本身的Modle,甚至不放。 Model的类型如下。 Model在具体实现中使用的方式有很多种,基于不同的功能与设计需求,Model通常 不会只有一种类型,而是会有多种类型。 最常见的Model多半是从数据源的结构而来,这些Model可能由DataSet或 DataTable构成,用来加载与数据源互动的数据,并将数据提供给应用程序使用。此类 Model的结构会和数据库架构相似,或是使用与数据库相同的命名规则设计,常见于以数 据库为中心(Database-Centric)的MVC 应用程序。 另一种Model依存于特定的程序或显示接口,此类Model会按照程序所需要的数据 结构进行设计,而不是针对数据源,最常见的是与显示接口相互沟通的Model,如 ViewModel,它们的存在与程序紧密结合,但通常与数据源无关,也就是数据是来自程序 的处理与计算,而不是来自数据源。 NET 的大师级人物Dio将ASP.l分为三 ASP.noEspositNETMVC 内使用的Mode 种,分别是DomainModel、ViewModel与InputModel。 .DomainModel:与前面所述的以数据源为主的Model很相似,但融入了领域驱动 设计的概念。 .ViewModel:与View紧密结合的Model类型。 .InputModel:是由用户端或外部系统端输入的Model,InputModel会和MVC 的ModelBinding机制协同合作,以提供简便的数据输入绑定方式。 无论何种类型,都可以看到一个共同的含义,就是Model并不限于数据,也可以是外 部服务或是程序(例如商业逻辑层), 所以,在进行Model的设计时不能只就数据面思考, 尤其是当程序和其他服务连接时。 3. 2 ORM 程序员除了掌握基本的程序设计语言外,若需要访问数据库,还必须额外学习SQL 指 令,才能处理数据库端的数据访问。而各种数据库都有自己的SQL 语法,像Oracle是PL/ SQL,SQLServer是Transact-SQL 等,SQL 本身又带有很强的关系型代数,以及基于架构 (Schema-based)的特性,再加上SQL 本身的指令和一般程序在概念上又不太相似(SQL 是 一种以集合为主的语言), 造成程序员在学习上的障碍。另外,数据库端可能还会有数据库 管理员(DataBaseAdministrator,DBA), 通常DBA 会严格监控程序员所写的SQL,因为SQL 写得好与坏关乎数据库的访问性能,而这也是令很多程序员十分棘手的问题。 28 ASP.NET MVC 程序开发实战 若能将对象自动与数据库进行映射,程序员就不必担心数据访问时还要写SQL的问 题,用他们所熟悉的方法就可方便地访问数据库,对象关系映射(ObjectRelational Mapping,ORM)的概念就是在这个基础上开发出来的。 ORM是指对象结构(Structure)和数据库架构(Schema)间的映射。使用ORM所设 计的系统,其内部对象和数据库架构都有一定的映射规则,程序员可以不必编写SQL,通 过ORM提供的MappingServices(映射服务),将上层的对象访问指令转换成对数据库 的SQL操作指令后,由数据库执行,再将运行结果封装成对象风格后返回给程序,所以程 序员只要熟悉对象的使用就能访问数据库,无须另外学习使用SQL 。 3.niyFreok概述 3 Ettamwr EntityFramework(简称EF)是一种ORM的数据访问框架,它主要为程序员提供更 轻松访问数据源的功能,并试着以ORM的架构让程序员不必为了编写SQL而费心。 EF结合了LINQ以及Expresion的功能,在核心层实现SQL生成器,以程序通过 IQueryable<T>指令传入的Expresion的内容,决定如何产生SQL指令,而且这些指 令都经过SQLServer工程团队的设计,特别为SQLServer进行了优化,所以程序员只要 会应用LINQ,就能很便捷地查询SQLServer数据库,而不必特别为了访问数据库而学 习一堆SQL指令。 虽然前面只讲了SQLServer,但其实EF本身是具有扩展性的框架,只要其他数据库 (如Oracle、MySQL或是DB2)按照EF提供的接口实现自己的SQL生成器与连接管理 机制,就可以让EF支持不同的数据库,事实上也已经有不少数据库提供商宣布或实现支 持EF的数据提供程序。 EF利用数据库建模(DatabaseModeling)的方法将程序代码与数据库架构结合起 来,以支持对象与数据库架构的串接,程序员可利用VisualStudio内的ADO.NET实体 数据模型(EntityDataModel)文件调用EF的实体数据模型向导。 EF包含三种建模方法,分别是数据库优先建模法(DataBaseFirst)、模型优先建模法 (ModelFirst),以及完全以程序代码建模的程序代码优先建模法(CodeFirst)。起初EF 用于开发时,只提供了数据库优先的建模方法, 到4. 由现有的数据库产生建模映射;0版 时,加入了模型优先建模法,允许程序员直接在项目中定义数据模型,再使用T4模板的 方法产生数据库的设计模型,之后通过DataContext的生成器将设计好的模型送到数据 库系统内以产生数据库。 EniyFamer0版中推出了前面提到的程序代码优先模型,程序员只需要定 ttrwok5. 义出要使用的数据模型,然后在程序代码中设置数据模型间的关系,以及设置各属性的特 征(例如它是IDENTITY,或是允许NULL等),然后利用DbContext对象按照这些设置 建立数据库,至于要用什么SQL指令,就不是程序员担心的了。 实际使用哪种类型的数据建模法,要由团队的成员配置与职务而定。若是新项目,又 是以程序员为主的团队,则使用CodeFirst方法较佳;若有数据库管理员,则应考虑使用 DataBaseFirst或是ModelFirst方法,由数据库管理员进行设计,再由程序员根据模型编 29 第 3 章 模型和数据操作 写程序。另外,若使用的数据库是现有的,建议使用DataBaseFirst或是CodeFirst方 法,若是新建数据库,则考虑使用ModelFirst或CodeFirst方法。 在VisualStudio开发环境下学习数据库应用编程时,用它自带的SQLServer ExpresLocalDB数据库实现即可,这种数据库的优点是用法简单,而且将项目和数据库 从一台计算机复制到另一台计算机上时,不需要对数据库做任何单独的额外操作。 LocalDB数据库实际上并不是为 IS设计的,但是,在开发环境下,由于LocalDB数 据库使用方便,而且开发完成后,将LocaIDB数据库移植到其他版本的数据库中也非常 容易(只需要修改项目根目录下Web.g中的数据库连接字符串即可,其他代码不需 confi 要做任何改变)。因此,本书中开发Web应用程序项目,采用LocaIDB数据库实现。 3.3.1 DataBase First DataBaseFirst模式称为“数据库优先”,该模式假设已经有相应的数据库,可以使用 EF设计工具根据数据库生成数据类,并使用VisualStudio模型设计器修改这些模型之 间的对应关系。 ADO. 首先创建一个控制台应用程序,然后创建实体模型,添加新建项,选择“NET实 体数据模型”表示要使用实体数据模型,并且使用EntityModelDesigner编辑。选择 ADO.1所示。 NET实体数据模型如图3. 图3.选择ADO. 1 NET实体数据模型 下面需要与现有的数据库进行连接生成EF实体,在进行这一步之前,首先确定是否 已经有现成的数据库,单击“添加”按钮,进入实体数据模型向导页面,如图3. , 2所示。 若使用DataBaseFirst方式,其实体数据模型选择“来自数据库的EF设计器”单击 “下一步” 如图3. 按钮进入设置数据库连接字符串的屏幕显示页面,3所示。 30 ASP.NET MVC 程序开发实战 图3.实体数据模型向导 2 图3.选择数据连接 3 31 第 3 章 模型和数据操作 若“您的应用程序应使用哪个数据连接与数据库进行连接?” 下拉菜单为空,请单击右 边的“新建连接”按钮设置新的数据连接。数据源可以是SQLServer数据库,也可以是数 据库文件,如图3. 4所示。 图3.设置数据源 4 连接设置完成时,会回到“连接属性”对话框,并且默认存储连接字符串到App. config(若是ASP.config), 名称默认为Modentities字 NET 应用程序则是Web.l的名称加上E 样,以本例来说就是BookManagerEntities,单击“下一步”按钮会出现选用何种EF 版本 的对话框,如图3. 5所示。 图3.选择实体框架版本 5 选择最新版本实体框架6.单击“完成”按钮,弹出“选择您的数据库对象和设置”页 面,如图3. x, 6所示。 32 ASP.NET MVC 程序开发实战 图3.选择数据库对象 6 在“选择您的数据库对象和设置”页面中首先需要选择在模型中包括哪些数据库对 象,选择项包括数据“表”“视图”及“存储过程和函数”,此外还有三个选项:第一个选项是 “确定所生成对象名称的单复数形式”,这个选项的功能是要求EF 在生成类对象时,分析 数据库的名称决定Entity、EntitySet及NavigationProperty三者的名称是单数或是复 数。第二个选项是“在模型中包括外键列”,表示要在生成出来的Model中加入 NavigationProperty,不过只限于数据表内有明确设置ForeignKeyConstraint的才会加 入。第三个选项是“将所选存储过程和函数导入实体模型中”,表示若选择了存储过程和 函数,向导会将这些存储过程和函数的设置加到实体模型内,这样就可以利用 ObjectContext<T> 的ExecuteFunction() 调用,而不需使用ExecuteStoreCommand() 调用。 选择好要导入模型的数据库对象和三个选项后,如果不需要修改模型命名空间,单击 “完成”按钮,系统会帮助生成数据库实体类及EDMX 的定义文件。 生成的文件目录如图3. 7所示。 创建完实体模型后,会自动生成Books、BookTypes、Roles、Users和Carts实体类和 一个Boongrttes数据库上下文操作类, ledmx 会显示如图3. kMaaeEnii双击Mode1.8所 示的实体关系图。 第 3 章 模型和数据操作 33 图3.生成的文件目录 7 图3.实体关系图 8 34 ASP. NET MVC 程序开发实战 使用DataBaseFirst所生成的模型,会使用T4 (TextTemplateTransformation Toolkit)模板进行转换,在项目内的.tt文件就是文字模板(TextTemplate)文件,它是用 来生成数据库对象所对应的程序代码文件。 这样就拥有访问数据库的模型了,只要编写简单的数据访问代码,就可以对数据库进 行增加、删除、修改、查找操作了。下面简单看一下如何使用EF进行数据查询,通过下面 的代码可以看到EF对于数据的操作非常容易。 static void Main(string[] args) { using (var db = new BookManagerEntities()) { IQueryable<Books> books = from book in db.Books where book.Author == "王雪" select book; foreach (Books p in books) { Console.WriteLine("书名是:{0}", p.Title); } } Console.ReadLine(); } 在程序入口的Main()函数中实例化BookManagerEntities数据操作类,使用Linq语 句对Books中的数据做投影查询,过滤条件为作者“王雪”,最后输出到控制台。运行结 果如图3.9所示。 图3.9 运行结果 3.3.2 Model First ModelFirst是EF4开始新增的功能,主要提供给目前没有数据库,但又需要使用 EF设计模型的程序员使用。正如其名,程序员要先在Designer内设计好模型的结构,再 利用这个结构生成数据库。 首先,与DataBaseFirst一样,新增一个ADO.NET 实体数据模型,但这次选择的是 “空EF设计器模型”,然后单击“完成”按钮,如图3.10所示。 这时会出现一个空白的Designer,并且工具箱也会出现必要的模板,就像使用 WindowsForms的窗体设计器一样,由工具箱拖拉出模板放到Designer的空间内,以此 建立模型。建立模型空窗体如图3.11所示。 第 3 章 模型和数据操作 35 图3.选择实体数据模型 10 图3.建立模型空窗体 11 36 ASP.NET MVC 程序开发实战 接着,建立数据模型,方法很简单,从左边的“工具箱”中将“实体”拖放到Designer内,就会 产生一个新的模型,然后将名称改为Roles和Users,并在模型上右击,从弹出的快捷菜单中选 择“新增” 标量属性”命令,并给其命名,设计好实体后可以添加关联关系,如图312 所示。 →“ . 图3.建立模型及关联关系 12 下面设置每个字段的数据类型,在字段上右击,从弹出的快捷菜单中选择“属性”命 令,在“属性”窗口的“类型”中选择所需的类型即可,如图3.13 所示。 图3.设置字段属性 13 第 3 章 模型和数据操作 37 在建立关联的同时,还会产生“导航属性”选项,通过导航属性,就能直接浏览关联好 的对象。设置完成后,在Designer的空白处单击,可以看到属性窗口内会出现关于这个 Model的设置,将“以复数形式表示新对象”设为true,会让User在产生数据表时将名称 设为Users,Role会设为Roles。至此,设计已经完成,但要将它生成为数据库之前,还需 要做一个设置,就是需要一个DbContext对象。要产生DbContext对象的方法也不难, 只要在Designer上右击,选择“添加代码生成项”命令即可,如图3. 14 所示。 图3.根据模型生成代码 14 此时会出现添加DbConet生成器的选项,选择“EF6.otxt生成器”,可以 txxDbCne 修改Model的名字,再单击“添加”按钮,如图3. 15 所示。 图3.选择生成DbCt的生成器 15 ontex 38 ASP.NET MVC 程序开发实战 此时就能在项目中看到Modeledmx下出现了Modlcnett 文件,以及 1.e1.otx. Mode1.下包含了Mode1.otxcs及在Dsgnr中所设计的Model的程序代码文 lt lCneteie 件。在Designer的空白处右击,从弹出(.) 的快捷菜单中选择“根据模型生成数据库”命令, 如图3. 16所示。 图3.根据模型生成数据库 16 下一步是设置数据库连接属性,数据源选择MicrosoftSQLServer数据库文件 (SqlClient),输入数据库文件名后,单击“ 按钮, 17所示。 确定” 如图3. 图3.设置数据库连接属性 17 39 第 3 章 模型和数据操作 在数据连接的窗口中设置要连接的数据库,在“使用那个数据库连接与数据库进行连 接”下拉菜单中输入BookModel,然后单击“确定”按钮,这时会出现是否要建立新数据库 的对话框,单击“是”按钮,建立新数据库。接着会出现数据库架构脚本生成的屏幕显示画 面,如图3. 18 所示。 图3.设置数据库连接属性 18 单击“完成” ViulSui如图3. 按钮,satdo将自动生成DDL 文件并打开, 19 所示。 ModelFirst生成数据库及数据对象后,就可以使用程序代码处理数据库的访问工作 了,这部分与DatabaseFirst、CodeFirst都一样,所以留在CodeFirst的部分一起说明。 3.3.3 Code First CodeFirst模式最早是从EF4 开始的,利用EF6 模板和已存在的数据库创建实体 模型在前面的学习中已经介绍,EF6(EntityFramework6)提供的CodeFirst模式分为 两种情况:一种情况是数据库已经存在,如果系统开发前已经存在数据库,则选择“来自 数据库的CodeFirst,(”) 步骤和DatabaseFirst类似,在该模式中取消了edmx 模型和T4 模板,直接生成EF 上下文和相应的类,该模式出现在VisualStudio2015 版本以后。 另一种情况是还不存在数据库,那么选择“空CodeFirst模型”,添加完成后,Visual Studio会打开生成好的CodeFirst程序代码。正如CodeFirst,定义的规则全部由程序 代码处理,所以这也意味着使用CodeFirst方式进行建模时,可以直接使用类的程序代 码,而不一定用ADO. NET 实体数据模型的方式产生。 40 ASP.NET MVC 程序开发实战 图3. 19 DDL 文件 创建一个控制台应用程序,然后添加新建项,选择“ADO.NET 实体数据模型”,弹出 实体数据模型向导,如图3. 20 所示。 图3.实体数据模型向导 20 第3 章 模型和数据操作 41 EF6提供的“来自数据库的CodeFirst”模板适用于数据库已经存在的情况,利用它 可自动生成C#模型类代码和C#数据上下文类代码。或者说,利用该模板既可以根据 生成的代码理解数据库表中字段类型和C#数据类型之间的对应关系,又可以简化Code First代码编写的工作量。 “空CodeFirst模型”和“来自数据库的CodeFirst”用法相似,适用于不存在数据库, 但是希望借助它先帮助自动生成部分C# 代码的情况。和前面的DataBaseFirst与 ModelFirst一样,可以通过添加ADO.NET实体数据模型生成模型。 本节主要介绍数据库不存在时CodeFirst模式的基本用法,目的是让读者理解相关 的概念。但是一定要记住,CodeFirst模式既可用于现有数据库,也可以创建数据库。在 实体数据模型向导中选择“空CodeFirst模型”,系统会自动生成一个类。注意,自动生成 的模型都需要继承自DbContext,可以看到,微软已经给了很多提示,例如,需要自己配置 连接数据库的字符串;创建的模型类都需要在DbContext实体类中添加DbSet,代码如下 所示。 几乎所有的管理软件都具有权限管理。下面新建两个模型类用户模型Users和角色 模型Roles,用于对图书馆里系统的权限进行管理。需要根据提示引入相应的命名空间, 使用构造函数设置属性初值,并且需要用Key为自己的表指定主键。 public class Roles { public Roles() { Users = new HashSet<Users>(); } [key] public int RoleID { get; set; } public string RoleName { get; set; } public virtual ICollection<Users> Users; 42 ASP. NET MVC 程序开发实战 } public class Users { public Users() { IsValid = true; Birth = DateTime.Now; Sex = "男"; RoleID = 3; } [key] public int UserId { get; set; } public string UserName { get; set; } public string Password { get; set; } public string Sex { get; set; } public DateTime? Birth { get; set; } public string City { get; set; } public string Phone { get; set; } public string Email { get; set; } public string Address { get; set; } public bool IsValid{ get; set; } public int RoleID { get; set; } public Roles Roles { get; set; } } 在Roles和Users模型中,除了将数据库中的字段定义为类的属性外,还为Roles添 加了类型为ICollection<Users>的Users对象,并在构造方法中实例化;为Users模型 添加类型为Roles的Roles对象,表明Roles和Users模型的关系为一对多。 定义好模型后,需要按照微软提供的模板将这两个类添加到DbSet。这里的“name = Model1”表示使用名字为Model1的字符串连接数据库。 public class Model1:DbContext { //连接字符串 public Model1() : base("name=Model1") { } public virtual DbSet<Roles> Roles { get; set; } public virtual DbSet<Users> Users { get; set; } } 下面是项目根目录下的App.config中数据库连接字串的配置,名为Model1的连接 字串对应的数据库名称为EFConsoleApp.Model1。 第3 章 模型和数据操作 43 <connectionStrings> < add name =" Model1" connectionString =" data source = (LocalDb) \MSSQLLocalDB; initial catalog = EFConsoleApp. Model1; integrated security = True; MultipleActiveResultSets= True; App = EntityFramework" providerName =" System. Data.SqlClient" /> </connectionStrings> 然后在Program 的Main()函数中写操作数据库的代码,用来生成数据库。 static void Main(string[] args) { using (var db = new Model1()) { var role = new Roles(); role.RoleName = "超级管理员"; db.Roles.Add(role); role = new Roles(); role.RoleName = "管理员"; db.Roles.Add(role); role = new Roles(); role.RoleName = "普通用户"; db.Roles.Add(role); db.SaveChanges(); IQueryable<Roles> roles = from r in db.Roles select r; foreach (Roles r in roles) { Console.WriteLine("角色是:{0}", r.RoleName); } } Console.ReadLine(); } 定义并实例化数据库操作类Model1,为Roles表添加超级管理员、管理员和普通用 户后,执行db.SaveChanges()语句将数据保存在数据库中。运行程序,可以看到运行结 果如图3.21所示。 图3.21 运行结果 44 ASP. NET MVC 程序开发实战 程序运行后,在控制台中查询到三条角色列表,说明使用CodeFirst方式创建了数据 库,并且包含Roles和Users两张表,Roles表中插入了以上三条数据,那么创建的数据库 文件在哪里呢? 可以打开VisualStudio视图菜单下的SQLServer对象资源管理器查看数据库文 件,使用CodeFirst方式生成的数据库如图3.22所示。 图3.22 使用CodeFirst方式生成的数据库 3.3.4 数据库初始化 在系统开发初期,通常不会有数据库,要自行创建数据库之后,才能进行后续程序的 开发。按照ORM 的概念,程序员应该不需要编写CREATEDATABASE 语句,所以 DbContext提供了两个方法创建数据库,分别是Create()、CreateIfNotExists(),前者可 创建数据库,但若数据库己存在,则会弹出提示;后者会判断数据库是否已存在,若存在, 则不做任何动作,否则会创建数据库。有新增数据库的指令,当然也会有删除数据库的指 令,若要删除数据库,只要调用Delete()即可。 db.Database.Create(); db.Database.CreateIfNotExists(); db.Database.Delete(); 不过,对于程序员来说,数据库的新增和删除不是重点,重点是在新增数据库时要额 外做一些数据新增的工作,这在部署系统时很常见,每次在部署有数据库的系统时,都要 产生大量SQL指令带到目标环境执行,对程序员来说并不十分方便,因此ORM 通常会 提供一些方法处理这部分工作。EF 在这部分提供了数据库初始化器(DataBase Initializer)的功能,内建了以下4种方法。 第3 章 模型和数据操作 45 . 在数据库不存在时创建数据库 Database.SetInitializer<Model1>(new CreateDatabaseIfNotExists< Model1>()); . 在模型更改时创建数据库 Database.SetInitializer<Model1>(new DropCreateDatabaseIfModelChanges < Model1>()); . 每次启动应用程序时创建数据库 Database.SetInitializer<Model1>(new DropCreateDatabaseAlways < Model1>()); . 从不创建数据库 Database.SetInitializer< Model1>(null); 除此之外,EF也提供了IDatabaseInitializer<TContext>接口供程序员使用,以开 发出适合自己数据库初始化器的功能,并且可加入一些所需的新增数据。IDatabase- Initialize<TContex>只有一个方法InitializeDatabase(),只实现这个方法即可,例如: public class DbInit:IDatabaseInitializer< Model1> { public void InitializeDatabase(Model1 context) { context.Database.CreateIfNotExists(); context.Users.Add( new Users() { UserName = "Test", Password = "t123", Phone = "18695553888", Email = "wangyy@163.com" }); context.SaveChanges(); } } 若要驱动DbInit类,需要两步:首先是设置要使用的初始化器,可用Database. SetInitializer()实现;然后是在DbContext的生命周期内调用DbContext.Initialize(),并 传入是否要强制执行DatabaseInitializer的参数。 Database.SetInitializer<Model1>(new DbInit()); using (var db = new Model1()) { db.Database.Initialize(true); }