您现在的位置是:网站首页> 编程资料编程资料
Entity Framework实现数据迁移_实用技巧_
2023-05-24
257人已围观
简介 Entity Framework实现数据迁移_实用技巧_
一、合并和迁移
1、合并
合并是指“新的实体模型映射到数据库中,更新其结构”,例如:
新增了实体类,表现在数据库中就是新增加实体类对应的数据表。
删除了实体类,表现在数据库中就是删除了实体类对应的数据表。
在一个已经存在的实体类中增加属性,表现在数据库中就是在实体类对应的数据表中新增加字段。
在一个已经存在的实体类中删除属性,表现在数据库中就是在实体类对应的数据表中删除字段。
修改一个已经存在的实体类中属性的名称或类型,表现在数据库中就是修改实体类对应的数据表中字段的名称或类型。
2、迁移
迁移是指“在更新数据库结构时,把老结构中的数据迁移到新结构中”。
二、迁移前的准备工作
搭建项目结构,整体的项目结构包括一个控制台应用程序和两个类库,项目结构如下:

其中EF.Application是控制台程序,EF.FluentAPI和EF.Model是类型,EF.Model里面存的是实体类,EF.FluentAPI是实体类的Map类,用来设置FluentAPI。
Student类结构如下:
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; } } }StudentMap类结构如下:
using EF.Model; using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations.Schema; using System.Data.Entity.ModelConfiguration; using System.Linq; using System.Text; using System.Threading.Tasks; namespace EF.FluentAPI { /// /// 使用FluentAPI配置 /// public class StudentMap :EntityTypeConfiguration { public StudentMap() { // 配置数据库中生成的表的名称 this.ToTable("Students"); // 设置StudentID列自动增长 this.Property(p => p.StudentID).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity); // 设置StudentID列作为主键 this.HasKey(p => p.StudentID); // 设置StudentName列的类型是nvarchar,最大长度是50,必须的 this.Property(p => p.StudentName).HasColumnType("nvarchar").HasMaxLength(50).IsRequired(); // 设置Age列是必须的 this.Property(p => p.Age).IsRequired(); // 设置Sex的类型是nvarchar this.Property(p => p.Sex).HasColumnType("nvarchar").IsRequired(); } } } EF上下文类结构:
using System; using System.Collections.Generic; using System.Data.Entity; using System.Linq; using System.Text; using System.Threading.Tasks; namespace EF.FluentAPI { public class EFDbContext:DbContext { public EFDbContext() : base("name=CodeFirstApplication") { } protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Configurations.Add(new StudentMap()); } } }数据库连接字符串:【注意:在EF.Application和EF.FluentAPI的App.config里面都要添加上该连接字符串】
控制台程序:
using EF.FluentAPI; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using EF.Model; namespace EF.Application { class Program { static void Main(string[] args) { Console.WriteLine("请输入学生姓名:"); string studentName = Console.ReadLine().Trim(); Console.WriteLine("请输入学生年龄:"); int age = 0; if (!int.TryParse(Console.ReadLine().Trim(), out age)) { Console.WriteLine("年龄只能输入正整数,请重新输入:"); return; } Console.WriteLine("请输入学生性别(男/女):"); string sex = Console.ReadLine().Trim(); using (var context = new EFDbContext()) { Student student = new Student() { StudentName=studentName, Age=age, Sex=sex }; context.Entry(student).State = System.Data.Entity.EntityState.Added; // 保存 context.SaveChanges(); } Console.Write("添加成功"); Console.ReadKey(); } } }运行程序:

查看数据库:

其中生成的表__MigrationHistory用来记录每次的迁移。
三、迁移
现在我们在Student实体类中增加Grade字段,整体项目做如下的改动:
Student类:
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字段,用来实现数据迁移 public string Grade { get; set; } } }StudentMap类:
using EF.Model; using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations.Schema; using System.Data.Entity.ModelConfiguration; using System.Linq; using System.Text; using System.Threading.Tasks; namespace EF.FluentAPI { /// /// 使用FluentAPI配置 /// public class StudentMap :EntityTypeConfiguration { public StudentMap() { // 配置数据库中生成的表的名称 this.ToTable("Students"); // 设置StudentID列自动增长 this.Property(p => p.StudentID).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity); // 设置StudentID列作为主键 this.HasKey(p => p.StudentID); // 设置StudentName列的类型是nvarchar,最大长度是50,必须的 this.Property(p => p.StudentName).HasColumnType("nvarchar").HasMaxLength(50).IsRequired(); // 设置Age列是必须的 this.Property(p => p.Age).IsRequired(); // 设置Sex的类型是nvarchar this.Property(p => p.Sex).HasColumnType("nvarchar").IsRequired(); // 设置Grade字段是必须的 this.Property(p => p.Grade).HasColumnType("varchar").HasMaxLength(16).IsRequired(); } } } 控制台:
using EF.FluentAPI; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using EF.Model; namespace EF.Application { class Program { static void Main(string[] args) { Console.WriteLine("请输入学生姓名:"); string studentName = Console.ReadLine().Trim(); Console.WriteLine("请输入学生年龄:"); 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

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

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

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

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

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

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

查看数据库:

输入的数据保存到数据库中。
四、修改属性
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

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

查看201711290052153_ModifyGrade类结构:
namespace EF.FluentAPI.Migrations { using System; using System.Data.Entity.Migrations; public partial class ModifyGrade : DbMigration { public override void Up() {
相关内容
- VS2019中.NET如何实现打日志功能_实用技巧_
- Entity Framework使用配置伙伴创建数据库_实用技巧_
- Entity Framework使用DbModelBuilder API创建表结构_实用技巧_
- EF使用数据注解特性创建表结构_实用技巧_
- 使用Spring.Net框架实现多数据库_实用技巧_
- 配置Spring.Net框架开发环境_实用技巧_
- Spring.Net框架简介_实用技巧_
- 如何判断 .NET Core 应用程序以管理员身份运行的_实用技巧_
- ASP.NET Core基于滑动窗口实现限流控制_实用技巧_
- EF使用Code First模式生成单数形式表名_实用技巧_
点击排行
本栏推荐
