Entity Framework实现数据迁移

2022-04-17 08:28:09

一、合并和迁移

1、合并

合并是指“新的实体模型映射到数据库中,更新其结构”,例如:
新增了实体类,表现在数据库中就是新增加实体类对应的数据表。
删除了实体类,表现在数据库中就是删除了实体类对应的数据表。
在一个已经存在的实体类中增加属性,表现在数据库中就是在实体类对应的数据表中新增加字段。
在一个已经存在的实体类中删除属性,表现在数据库中就是在实体类对应的数据表中删除字段。
修改一个已经存在的实体类中属性的名称或类型,表现在数据库中就是修改实体类对应的数据表中字段的名称或类型。

2、迁移

迁移是指“在更新数据库结构时,把老结构中的数据迁移到新结构中”。

二、迁移前的准备工作

搭建项目结构,整体的项目结构包括一个控制台应用程序和两个类库,项目结构如下:

int age = 0; if (!int.TryParse(Console.ReadLine().Trim(), out age)) { Console.WriteLine("年龄只能输入正整数,请重新输入:"); return; } Console.WriteLine("请输入学生性别(男/女):"); string sex = Console.ReadLine().Trim(); Console.WriteLine("请输入年级:"); string grade = Console.ReadLine().Trim(); using (var context = new EFDbContext()) { Student student = new Student() { StudentName=studentName, Age=age, Sex=sex, Grade=grade }; context.Entry(student).State = System.Data.Entity.EntityState.Added; // 保存 context.SaveChanges(); } Console.Write("添加成功"); Console.ReadKey(); } }}

启用数据迁移:

1、打开迁移

在程序包管理器控制台中输入:Enable-Migrations

EntityFramework实现数据迁移

按回车键后,会生成Migrations文件夹,以及Migrations文件夹下面的Configuration类和201711281316287_InitialCreate类:

EntityFramework实现数据迁移

Configuration:这个类允许你去配置如何迁移,对于本文将使用默认的配置(在本文中因为只有一个Context,Enable-Migrations将自动对context type作出适配);

201711281316287_InitialCreate:这个迁移之所以存在是因为我们之前用Code First创建了数据库,在启用迁移之前,scaffolded migration里面的代码表示在数据库中已经创建的对象,本文中即为表Students。

Code First Migrations有两个需要熟悉的命令:
Add-Migration 将scaffold创建下一次基于上一次迁移以来的更改的迁移;
Update-Database 将任何挂起的迁移应用到数据库;

以上面新增加的字段Grade属性为例,命令Add-Migration允许我们对迁移进行命名,我们把迁移命名为AddGrade。

2、增加迁移节点

在程序包管理器控制台中输入命令:Add-Migration AddGrade

EntityFramework实现数据迁移

一个新的迁移(201711281402492_AddGrade)在目录Migrations中创建成功:

EntityFramework实现数据迁移

201711281402492_AddGrade类结构如下:

namespace EF.FluentAPI.Migrations{    using System;    using System.Data.Entity.Migrations;    public partial class AddGrade : DbMigration    {        public override void Up()        {            AddColumn("dbo.Students", "Grade", c => c.String(nullable: false, maxLength: 16, unicode: false));        }        public override void Down()        {            DropColumn("dbo.Students", "Grade");        }    }}

201711281402492_AddGrade的名称是上面Add后面定义的迁移名称,而类下面有两个方法:一个是Up,一个是Down,记录了需要升级的修改,这里也就是Students表增加了Grade列。只要我们在后面执行Update-Database,就会执行此类下面的Up函数。

这里的Down函数简单介绍就是:为了回滚修改而设计的。如果用户希望恢复到某一个迁移节点,程序会自动根据已经执行的迁移,判断回滚哪些迁移,执行他们的Down函数。

3、更新数据库

在程序包管理器控制台中输入命令:Update-Database -Verbose

EntityFramework实现数据迁移

查看数据库,Students表已经增加Grade字段:

EntityFramework实现数据迁移

到此为止,迁移已经完成,再次运行项目:

EntityFramework实现数据迁移

查看数据库:

EntityFramework实现数据迁移

输入的数据保存到数据库中。

四、修改属性

1、将Student实体类中的Grade属性的名称修改为GradeTest:

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;namespace EF.Model{    public class Student    {        public int StudentID { get; set; }        public string StudentName { get; set; }        public int Age { get; set; }        public string Sex { get; set; }        // 将Grade属性名修改为GradeTest        public string GradeTest { get; set; }    }}

2、增加迁移节点

在程序包管理器控制台中输入命令:Add-Migration ModifyGrade

EntityFramework实现数据迁移

在Migrations文件夹下面会生成本次的迁移记录:201711290052153_ModifyGrade

EntityFramework实现数据迁移

查看201711290052153_ModifyGrade类结构:

namespace EF.FluentAPI.Migrations{    using System;    using System.Data.Entity.Migrations;    public partial class ModifyGrade : DbMigration    {        public override void Up()        {            AddColumn("dbo.Students", "GradeTest", c => c.String(nullable: false, maxLength: 16, unicode: false));            DropColumn("dbo.Students", "Grade");        }        public override void Down()        {            AddColumn("dbotSgJhpIZlf.Students", "Grade", c => c.String(nullable: false, maxLength: 16, unicode: false));            DropColumn("dbo.Students", "GradeTest");        }    }}

可以看到在Up方法里面,它不是直接修改了列的名称,而是先增加了一个新列GradeTest,然后删除旧列Grade。这样执行会有一个后果:如果Grade列里面有数据,数据会全部丢失。

3、更新到数据库

在程序包管理器控制台中输入命令:Update-Database -Verbose

EntityFramework实现数据迁移

查看数据库表:

EntityFramework实现数据迁移

通过查看数据库表,会发现新增加了GradeTest列,原先的Grade列被删掉,数据也全部丢失。

五、删除属性

删除属性和增加属性的操作差不多

1、修改Student实体类,注释掉GradeTest属性:

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;namespace EF.Model{    public class Student    {        public int StudentID { get; set; }        public string StudentName { get; set; }        public int Age { get; set; }        public string Sex { get; set; }        // 将GradeTest属性删除        //public string GradeTest { get; set; }    }}

2、增加迁移节点

在程序包管理器控制台中输入命令:Add-Migration DeleteGradeTest

EntityFramework实现数据迁移

查看生成的迁移记录类:

EntityFramework实现数据迁移

201711290130110_DeleteGradeTest类里面的Up方法里面删除了GradeTest列。

3、更新到数据库

在程序包管理器控制台中输入命令:Update-Database -Verbose

EntityFramework实现数据迁移

查看数据库表,可以发现GradeTest列被删除掉:

EntityFramework实现数据迁移

六、迁移至指定的版本(包括后退)

到目前为止,我们进行迁移都是进行升级,但是有些时候我们需要升级或降级至指定版本,例如我们想迁移数据库至运行ModifyGrade迁移之后的状态,此时我们就可以使用-TargetMigration来降级到这个版本。

在程序包管理器控制台中输入命令:Update-Database -TargetMigration:ModifyGrade

EntityFramework实现数据迁移

这个命令将会运行201711290130110_DeleteGradeTest类里面的Down命令。Reverting migrations表示回复迁移。

这时候在查看数据库表,会发现Students表中又有了GradeTest列。

如果你想回滚一切至空数据库,可以使用命令:Update-Database -TargetMigration:$InitialDatabase

EntityFramework实现数据迁移

这时候在查看数据库,发现Students表中所有列都已经被删除:

EntityFramework实现数据迁移

七、如何在保留现有数据的基础上修改列名

查看DbMigration类,会发现该类下面有一个RenameColumn()的方法,使用该方法可以在不丢失数据的基础上修改列的名称:

EntityFramework实现数据迁移

1、修改Student实体类,将StudentName修改为Name。

2、在程序包管理器控制台中输入命令:Add-Migration RenameStudentName,生成迁移文件,手动修改迁移类文件,修改内容如下:

namespace EF.FluentAPI.Migrations{    using System;    using System.Data.Entity.Migrations;    public partial class RenameStudentName : DbMigration    {        public override void Up()        {            //AddColumn("dbo.Students", "Name", c => c.String(nullable: false, maxLength: 50));            AddColumn("dbo.Students", "GradeTest", c => c.String(nullable: false, maxLength: 16, unicode: false));            //DropColumn("dbo.Students", "StudentName");            Renamewww.easck.comColumn("dbo.Students", "StudentName", "Name");        }        public override void Down()        {            //AddColumn("dbo.Students", "StudentName", c => c.String(nullable: false, maxLength: 50));            DropColumn("dbo.Students", "GradeTest");            //DropColumn("dbo.Students", "Name");            RenameColumn("dbo.Students", "Name", "StudentName");        }    }}

3、执行Update-Database命令,数据库列名被自动修改。

EntityFramework实现数据迁移

这里值得注意的是:在执行Update命令时,程序会提醒操作者: Changing any part of an object name could break scripts and stored procedures。翻译为中文:更改对象名的任一部分都可能会破坏脚本和存储过程。及修改列名可能会导致存储过程及其他调用列的sql脚本失效。

查看数据库表发现列名已经修改:

EntityFramework实现数据迁移

注意:在实际开发中,不建议随便修改列名:可能会导致其他用的该列的地方调用失败。

总结:

1、迁移的关联在数据库的迁移历史表__MigrationHistory和项目的Migrations文件夹下的继承了DbMigration的cs文件。

2、Migrations文件夹下的继承了DbMigration的cs文件可以手动修改,这里的修改可以非常灵活,表格和表格字段的增删改,在这里都有。

代码下载地址:点此下载

到此这篇关于Entity Framework实现数据迁移的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持我们。