EF CodeFirst系列(9)---添加初始化数据和数据库迁移策略
1.添加初始化数据(Seed)
我们可以在初始化数据库的过程中给数据库添加一些数据。为了实现初始化数据(seed data)我们必须创建一个自定义的数据库初始化器(DB initializer),并重写其中的Seed方法。
下边的栗子展示在School数据库中给Standard表添加默认的数据:
第一步:创建自定义初始化器
//继承三种内置的初始化器中的DropCreateDatabaseAlways
public class SchoolDBInitializer : DropCreateDatabaseAlways<SchoolDBContext>
{
protected override void Seed(SchoolDBContext context)
{
IList<Standard> defaultStandards = new List<Standard>(); defaultStandards.Add(new Standard() { StandardName = "Standard 1", Description = "First Standard" });
defaultStandards.Add(new Standard() { StandardName = "Standard 2", Description = "Second Standard" });
defaultStandards.Add(new Standard() { StandardName = "Standard 3", Description = "Third Standard" }); context.Standards.AddRange(defaultStandards);
//初始化数据
base.Seed(context);
}
}
第二步.将自定义的数据库初始化器添加到context中
public class SchoolContext: DbContext
{
public SchoolContext(): base("SchoolDB")
{
Database.SetInitializer(new SchoolDBInitializer());
} public DbSet<Student> Students { get; set; }
public DbSet<Standard> Standards { get; set; }
}
2.数据库迁移策略
前边我们已经知道了EF中的数据库迁移策略(CreateDatabaseIfNotExists,DropCreateDatabaseIfModelChanges, and DropCreateDatabaseAlways.),但是因为这些策略都是删除旧的数据库然后创建一个新的数据库,所以使用这些策略会造成数据库中的数据(不是seed data的数据)、存储过程、触发器等内容丢失。
针对上边的问题,EF提供了一个新的数据库初始化器 MigrateDatabaseToLastestVersion,这个工具在实体模型改变时自动帮我们更新数据库,且不会造成数据丢失。
下边介绍两种更新数据库的方法:
1.自动迁移
第一步:
在程序包管理器控制台输入
enable-migrations –EnableAutomaticMigration:$true
执行成功后,EFAp创建了一个继承自DbMigrationConfiguration类的Configuration类,如下
internal sealed class Configuration : DbMigrationsConfiguration<EF6Demo.SchoolContext>
{
public Configuration()
{
AutomaticMigrationsEnabled = true;//自动迁移为true
AutomaticMigrationDataLossAllowed = true;//允许数据丢失,默认生成时没有这一项(不添加这一项时,只在添加/删除实体类时自动生成,如果我们删除了实体类的一个属性就会抛出异常)
ContextKey = "EF6Demo.SchoolContext";
} protected override void Seed(EF6Demo.SchoolContext context)
{
// This method will be called after migrating to the latest version. // You can use the DbSet<T>.AddOrUpdate() helper extension method
// to avoid creating duplicate seed data.
}
}
第二步:
把数据库初始化器添加到配置中,context代码如下:
public class SchoolContext : DbContext
{
public SchoolContext() {
//添加MigrateDatabaseToLatestVersion数据库初始化器
Database.SetInitializer(new MigrateDatabaseToLatestVersion<SchoolContext, Configuration>());
}
public virtual DbSet<Student> Students { get; set; }
public virtual DbSet<Standard> Standards { get; set; } protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
}
}
完成上边两步,当我们修改实体类时运行程序就会自动更新数据库。
2.使用代码迁移
上边我们了解了通过自动迁移来更新数据库,这里介绍通过代码更新数据库的方法。通过代码更新数据库的功能更强大,如我们可以给数据库的列添加默认值,添加计算列等。
使用代码迁移,我们在程序包控制台执行以下过程:
1.Enable-Migrations [-f]
这条命令会生成一个Configuration文件,当配置文件存在时可通过-f后缀强制覆盖旧文件。执行成功后添加了Migrations文件夹,文件夹中包含一个Configuration配置类,如下:

Configuration配置类代码如下:
internal sealed class Configuration : DbMigrationsConfiguration<EF6Demo.SchoolContext>
{
public Configuration()
{
AutomaticMigrationsEnabled = false;
ContextKey = "EF6Demo.SchoolContext";
} protected override void Seed(EF6Demo.SchoolContext context)
{
// This method will be called after migrating to the latest version. // You can use the DbSet<T>.AddOrUpdate() helper extension method
// to avoid creating duplicate seed data.
}
}
2.Add-Migration [MigName]
首先在context类中指定初始化器是MigrateDatabaseToLatestVersion初始化器,如下:
public class SchoolContext : DbContext
{
public SchoolContext() {
//添加MigrateDatabaseToLatestVersion数据库初始化器
Database.SetInitializer(new MigrateDatabaseToLatestVersion<SchoolContext, Configuration>()); }
public virtual DbSet<Student> Students { get; set; }
public virtual DbSet<Standard> Standards { get; set; } protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
}
}
在包管理器控制台执行:
Add-Migration FirstInit
这会在Migration文件夹中生成一个<stamp>_name的迁移类:

迁移类的代码如下:
public partial class FirstInit : DbMigration
{
//升级
public override void Up()
{
CreateTable(
"dbo.Standards",
c => new
{
StandardId = c.Int(nullable: false, identity: true),
StandardName = c.String(),
})
.PrimaryKey(t => t.StandardId); CreateTable(
"dbo.Students",
c => new
{
StudentId = c.Int(nullable: false, identity: true),
StudentName = c.String(),
Standard_StandardId = c.Int(),
})
.PrimaryKey(t => t.StudentId)
.ForeignKey("dbo.Standards", t => t.Standard_StandardId)
.Index(t => t.Standard_StandardId); }
//降级
public override void Down()
{
DropForeignKey("dbo.Students", "Standard_StandardId", "dbo.Standards");
DropIndex("dbo.Students", new[] { "Standard_StandardId" });
DropTable("dbo.Students");
DropTable("dbo.Standards");
}
}
我们可以看到迁移类中包含Up()和Down()方法,分别用于数据库的更新和回退。
3.Update-Database
① updata-database [-verbose]
在程序包控制台中执行这条命令时,会执行Add-Migration命令创建的最新的迁移文件,并更新数据库。
执行完上边三步数据库就生成了,以后当我们修改实体类时,执行Add-Migration [MigName]后再执行Update-Database [-verbose],就可方便地根据模型的变化更新数据库。
② update-database -TargetMigration:xxx
如果我们想回退到某一个版本时执行:
update-database -TargetMigration:FirstInit//数据库回退到第一次的版本
3.codeFirst中的设计器
我们知道codeFirst模式中不支持设计器,设计器对我们理解实体间关系还是很有用的,怎么在code-first中使用设计器呢?Visual Studio Marketplace.点击链接下载工具,安装即可,安装完成重启VS,在context上点击右键,然后会有一个Entity Framework选项,如下图:

点击ViewEntity Data Model选项就可以自动生成设计器,如下:

这个工具十分好用,同时也支持生成Model XML和DDL SQL推荐使用。
EF CodeFirst系列(9)---添加初始化数据和数据库迁移策略的更多相关文章
- EF CodeFirst系列(2)---CodeFirst的数据库初始化
1. CodeFirst的默认约定 1.领域类和数据库架构的映射约定 在介绍数据库的初始化之前我们需要先了解领域类和数据库之间映射的一些约定.在CodeFirst模式中,约定指的是根据领域类(如Stu ...
- 3.Code-First 约定(EF Code-First系列)
前面,我们已经了解了Code-First利用领域类,怎么为我们创建数据库的简单示例.现在我们来学习一下Code-First约定吧. 什么是约定 约定说白了,就是基于一套规矩办事,这里就是基于你定义好的 ...
- EF CodeFirst系列(3)---EF中的继承策略(暂存)
我们初始化数据库一节已经知道:EF为每一个具体的类生成了数据库的表.现在有了一个问题:我们在设计领域类时经常用到继承,这能让我们的代码更简洁且容易管理,在面向对象中有“has a”和“is a”关系 ...
- EF CodeFirst系列(1)---CodeFirst简单入门
1.什么是CodeFirst 从EF4.1开始,EF可以支持CodeFirst开发模式,这种开发模式特别适用于领域驱动设计(Domain Driven Design,大名鼎鼎的DDD).在CodeFi ...
- EF CodeFirst系列(6)---配置1对1,1对多,多对多关系
这一节介绍EF CodeFirst模式中的1对0/1,1对多,多对多关系的配置,只有梳理清楚实体间的关系,才能进行愉快的开发,因此这节虽然很简单但是还是记录了一下. 1. 1对0/1关系配置 1. 通 ...
- MySQL基础之 恢复数据和数据库迁移
1.mysql命令或者source命令恢复数据 这两个命令在进行恢复数据的时候要检查是否创建数据库.如果数据库不存在,则恢复失败. 数据库迁移 1.相同版本的mysql数据库之间的迁移. mysqld ...
- 4.DB Initialization(数据库初始化)[EF Code-First系列]
前面的例子中,我们已经看到了Code-First自动为我们创建数据库的例子. 这里我们将要学习的是,当初始化的时候,Code-First是怎么决定数据库的名字和服务的呢??? 下面的图,解释了这一切! ...
- EF CodeFirst系列(4)--- 数据注释属性
EFCodeFirst模式使用的是约定大于配置的编程模式,这种模式利用默认约定根据我们的领域模型建立概念模型.然后我们也可以通过配置领域类来覆盖默认约定. 覆盖默认约定主要用两种手段: 1.数据注释属 ...
- 2.简单的Code First例子(EF Code-First系列)
现在假想,我们想要为讴歌学校创建一个应用程序,这个程序需要能够来添加或者更新学生,分数,教师还有课程信息. 代替之前我们的做法:先是创建数据库,现在我们不这么做,我们先来创建领域类,首先我来创建两个简 ...
随机推荐
- 系统重装助手教你如何在Microsoft Edge中恢复“关闭所有选项卡”警告
在Microsoft Edge中,当您打开多个选项卡时,浏览器将显示“您要关闭所有选项卡吗?” 警告,以防止您意外关闭重要标签. 通常,在没有第二个想法的情况下,您会立即禁用此功能,检查提示中的“始终 ...
- log4j控制指定包下的日志
最近观察日志发现如下两个问题: 1.项目用的是springboot项目,整合了rabbitmq,项目启动后,会自动监控rabbitmq谅解是否正常,导致控制台一直输出监控日志,此时就想阻止该类日志输出 ...
- 【English 】20190319
BOKO鼻子['boʊkoʊ] pores毛孔['pɔ:z] cute漂亮可爱[kjut] DEKO-BOKO pores don't make a girl cute! ideal最理想的[aɪˈ ...
- Python爬虫 selenium
库的安装 pip3 install selenium 声明浏览器对象 from selenium import webdriver browser = webdriver.Chrome() brows ...
- gpio led学习
2.弄清楚寄存器,gpio等之间的关系,to thi tha 比如: https://www.ggdoc.com/bGludXggZ3Bpb_aTjeS9nA2/NmIzNDIyZGZmMTExZjE ...
- 通过BulkLoad快速将海量数据导入到Hbase
在第一次建立Hbase表的时候,我们可能需要往里面一次性导入大量的初始化数据.我们很自然地想到将数据一条条插入到Hbase中,或者通过MR方式等. 但是这些方式不是慢就是在导入的过程的占用Region ...
- 网络流二十四题之P2764 最小路径覆盖问题
题目描述 给定有向图 G=(V,E)G=(V,E) .设 PP 是 GG 的一个简单路(顶点不相交)的集合.如果 VV 中每个定点恰好在PP的一条路上,则称 PP 是 GG 的一个路径覆盖.PP中路径 ...
- 消耗CPU和内存的脚本
用法 ./shell.sh 4 (4为4内核) 查看cpu内核数量 > lscpu 执行后会出现一堆kill命令,方便kill掉进程 #!/bin/bash endless_loop() { e ...
- C. Maximal Intersection(STL)
这道题,关键在于怎么求多个区间的交集,使用multiset就可以 分别将 r , l 存在不同的mutiset中. 然后,我们来看一下 是不是 交集的 l 是最大的, 交集的 r 是最小的 #incl ...
- 【Topcoder 10689】TheSoccerDivOne
题意:给\(n\)个队伍的积分,它们要踢足球,每个队伍剩下4场没有踢. 问踢完后\(0\)队伍最高排名. 思路:首先想了贪心,可惜不对. 那么老实dp. 首先:每个队伍具体和哪个人踢了没有关系. 那么 ...