1.添加初始化数据(Seed)

  我们可以在初始化数据库的过程中给数据库添加一些数据。为了实现初始化数据(seed data)我们必须创建一个自定义的数据库初始化器(DB initializer),并重写其中的Seed方法。

  下边的栗子展示在School数据库中给Standard表添加默认的数据:

第一步:创建自定义初始化器

  1. //继承三种内置的初始化器中的DropCreateDatabaseAlways
  2. public class SchoolDBInitializer : DropCreateDatabaseAlways<SchoolDBContext>
  3. {
  4. protected override void Seed(SchoolDBContext context)
  5. {
  6. IList<Standard> defaultStandards = new List<Standard>();
  7.  
  8. defaultStandards.Add(new Standard() { StandardName = "Standard 1", Description = "First Standard" });
  9. defaultStandards.Add(new Standard() { StandardName = "Standard 2", Description = "Second Standard" });
  10. defaultStandards.Add(new Standard() { StandardName = "Standard 3", Description = "Third Standard" });
  11.  
  12. context.Standards.AddRange(defaultStandards);
  13.      //初始化数据
  14. base.Seed(context);
  15. }
  16. }

第二步.将自定义的数据库初始化器添加到context中

  1. public class SchoolContext: DbContext
  2. {
  3. public SchoolContext(): base("SchoolDB")
  4. {
  5. Database.SetInitializer(new SchoolDBInitializer());
  6. }
  7.  
  8. public DbSet<Student> Students { get; set; }
  9. public DbSet<Standard> Standards { get; set; }
  10. }

2.数据库迁移策略

  前边我们已经知道了EF中的数据库迁移策略(CreateDatabaseIfNotExists,DropCreateDatabaseIfModelChanges, and DropCreateDatabaseAlways.),但是因为这些策略都是删除旧的数据库然后创建一个新的数据库,所以使用这些策略会造成数据库中的数据(不是seed data的数据)、存储过程、触发器等内容丢失

  针对上边的问题,EF提供了一个新的数据库初始化器 MigrateDatabaseToLastestVersion,这个工具在实体模型改变时自动帮我们更新数据库,且不会造成数据丢失。

下边介绍两种更新数据库的方法:

1.自动迁移

第一步:

在程序包管理器控制台输入

  1. enable-migrations EnableAutomaticMigration:$true

执行成功后,EFAp创建了一个继承自DbMigrationConfiguration类的Configuration类,如下

  1. internal sealed class Configuration : DbMigrationsConfiguration<EF6Demo.SchoolContext>
  2. {
  3. public Configuration()
  4. {
  5. AutomaticMigrationsEnabled = true;//自动迁移为true
  6. AutomaticMigrationDataLossAllowed = true;//允许数据丢失,默认生成时没有这一项(不添加这一项时,只在添加/删除实体类时自动生成,如果我们删除了实体类的一个属性就会抛出异常)
  7. ContextKey = "EF6Demo.SchoolContext";
  8. }
  9.  
  10. protected override void Seed(EF6Demo.SchoolContext context)
  11. {
  12. // This method will be called after migrating to the latest version.
  13.  
  14. // You can use the DbSet<T>.AddOrUpdate() helper extension method
  15. // to avoid creating duplicate seed data.
  16. }
  17. }

第二步:

把数据库初始化器添加到配置中,context代码如下:

  1. public class SchoolContext : DbContext
  2. {
  3. public SchoolContext() {
  4. //添加MigrateDatabaseToLatestVersion数据库初始化器
  5. Database.SetInitializer(new MigrateDatabaseToLatestVersion<SchoolContext, Configuration>());
  6. }
  7. public virtual DbSet<Student> Students { get; set; }
  8. public virtual DbSet<Standard> Standards { get; set; }
  9.  
  10. protected override void OnModelCreating(DbModelBuilder modelBuilder)
  11. {
  12. base.OnModelCreating(modelBuilder);
  13. }
  14. }

完成上边两步,当我们修改实体类时运行程序就会自动更新数据库。

2.使用代码迁移

  上边我们了解了通过自动迁移来更新数据库,这里介绍通过代码更新数据库的方法。通过代码更新数据库的功能更强大,如我们可以给数据库的列添加默认值,添加计算列等。

  使用代码迁移,我们在程序包控制台执行以下过程:

1.Enable-Migrations [-f]

  这条命令会生成一个Configuration文件,当配置文件存在时可通过-f后缀强制覆盖旧文件。执行成功后添加了Migrations文件夹,文件夹中包含一个Configuration配置类,如下:

Configuration配置类代码如下:

  1. internal sealed class Configuration : DbMigrationsConfiguration<EF6Demo.SchoolContext>
  2. {
  3. public Configuration()
  4. {
  5. AutomaticMigrationsEnabled = false;
  6. ContextKey = "EF6Demo.SchoolContext";
  7. }
  8.  
  9. protected override void Seed(EF6Demo.SchoolContext context)
  10. {
  11. // This method will be called after migrating to the latest version.
  12.  
  13. // You can use the DbSet<T>.AddOrUpdate() helper extension method
  14. // to avoid creating duplicate seed data.
  15. }
  16. }

2.Add-Migration [MigName]

  首先在context类中指定初始化器是MigrateDatabaseToLatestVersion初始化器,如下:

  1. public class SchoolContext : DbContext
  2. {
  3. public SchoolContext() {
  4. //添加MigrateDatabaseToLatestVersion数据库初始化器
  5. Database.SetInitializer(new MigrateDatabaseToLatestVersion<SchoolContext, Configuration>());
  6.  
  7. }
  8. public virtual DbSet<Student> Students { get; set; }
  9. public virtual DbSet<Standard> Standards { get; set; }
  10.  
  11. protected override void OnModelCreating(DbModelBuilder modelBuilder)
  12. {
  13. base.OnModelCreating(modelBuilder);
  14. }
  15. }

在包管理器控制台执行:

  1. Add-Migration FirstInit

这会在Migration文件夹中生成一个<stamp>_name的迁移类:

迁移类的代码如下:

  1. public partial class FirstInit : DbMigration
  2. {
  3. //升级
  4. public override void Up()
  5. {
  6. CreateTable(
  7. "dbo.Standards",
  8. c => new
  9. {
  10. StandardId = c.Int(nullable: false, identity: true),
  11. StandardName = c.String(),
  12. })
  13. .PrimaryKey(t => t.StandardId);
  14.  
  15. CreateTable(
  16. "dbo.Students",
  17. c => new
  18. {
  19. StudentId = c.Int(nullable: false, identity: true),
  20. StudentName = c.String(),
  21. Standard_StandardId = c.Int(),
  22. })
  23. .PrimaryKey(t => t.StudentId)
  24. .ForeignKey("dbo.Standards", t => t.Standard_StandardId)
  25. .Index(t => t.Standard_StandardId);
  26.  
  27. }
  28. //降级
  29. public override void Down()
  30. {
  31. DropForeignKey("dbo.Students", "Standard_StandardId", "dbo.Standards");
  32. DropIndex("dbo.Students", new[] { "Standard_StandardId" });
  33. DropTable("dbo.Students");
  34. DropTable("dbo.Standards");
  35. }
  36. }

我们可以看到迁移类中包含Up()和Down()方法,分别用于数据库的更新和回退。

3.Update-Database

① updata-database [-verbose]

  在程序包控制台中执行这条命令时,会执行Add-Migration命令创建的最新的迁移文件,并更新数据库

执行完上边三步数据库就生成了,以后当我们修改实体类时,执行Add-Migration [MigName]后再执行Update-Database [-verbose],就可方便地根据模型的变化更新数据库。

② update-database -TargetMigration:xxx

如果我们想回退到某一个版本时执行:

  1. 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)---添加初始化数据和数据库迁移策略的更多相关文章

  1. EF CodeFirst系列(2)---CodeFirst的数据库初始化

    1. CodeFirst的默认约定 1.领域类和数据库架构的映射约定 在介绍数据库的初始化之前我们需要先了解领域类和数据库之间映射的一些约定.在CodeFirst模式中,约定指的是根据领域类(如Stu ...

  2. 3.Code-First 约定(EF Code-First系列)

    前面,我们已经了解了Code-First利用领域类,怎么为我们创建数据库的简单示例.现在我们来学习一下Code-First约定吧. 什么是约定 约定说白了,就是基于一套规矩办事,这里就是基于你定义好的 ...

  3. EF CodeFirst系列(3)---EF中的继承策略(暂存)

    我们初始化数据库一节已经知道:EF为每一个具体的类生成了数据库的表.现在有了一个问题:我们在设计领域类时经常用到继承,这能让我们的代码更简洁且容易管理,在面向对象中有“has  a”和“is a”关系 ...

  4. EF CodeFirst系列(1)---CodeFirst简单入门

    1.什么是CodeFirst 从EF4.1开始,EF可以支持CodeFirst开发模式,这种开发模式特别适用于领域驱动设计(Domain Driven Design,大名鼎鼎的DDD).在CodeFi ...

  5. EF CodeFirst系列(6)---配置1对1,1对多,多对多关系

    这一节介绍EF CodeFirst模式中的1对0/1,1对多,多对多关系的配置,只有梳理清楚实体间的关系,才能进行愉快的开发,因此这节虽然很简单但是还是记录了一下. 1. 1对0/1关系配置 1. 通 ...

  6. MySQL基础之 恢复数据和数据库迁移

    1.mysql命令或者source命令恢复数据 这两个命令在进行恢复数据的时候要检查是否创建数据库.如果数据库不存在,则恢复失败. 数据库迁移 1.相同版本的mysql数据库之间的迁移. mysqld ...

  7. 4.DB Initialization(数据库初始化)[EF Code-First系列]

    前面的例子中,我们已经看到了Code-First自动为我们创建数据库的例子. 这里我们将要学习的是,当初始化的时候,Code-First是怎么决定数据库的名字和服务的呢??? 下面的图,解释了这一切! ...

  8. EF CodeFirst系列(4)--- 数据注释属性

    EFCodeFirst模式使用的是约定大于配置的编程模式,这种模式利用默认约定根据我们的领域模型建立概念模型.然后我们也可以通过配置领域类来覆盖默认约定. 覆盖默认约定主要用两种手段: 1.数据注释属 ...

  9. 2.简单的Code First例子(EF Code-First系列)

    现在假想,我们想要为讴歌学校创建一个应用程序,这个程序需要能够来添加或者更新学生,分数,教师还有课程信息. 代替之前我们的做法:先是创建数据库,现在我们不这么做,我们先来创建领域类,首先我来创建两个简 ...

随机推荐

  1. Python Learning: 01

    After a short period of  new year days, I found life a little boring. So just do something funny--Py ...

  2. ibm z14大型主机介绍

    IBM z14™大型主机 (z14)被设计为数字经济中值得信任的基础架构.它提供  特性和功能以满足对于新服务和更佳客户体验的需求,同时保护日益  增长的数据量,并遵从日益复杂的法规.IBM z14 ...

  3. PowerDesigner导出SQL,注释为空时以name代替

    版本 操作步骤 打开Edit Current DBMS 选中Script->Objects->Column->Add 将Value中的内容全部替换为如下 %20:COLUMN% [% ...

  4. Spring Boot使用注解实现AOP

    第一步: 添加依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactId& ...

  5. (原创)超详细一步一步在eclipse中配置Struts2环境,无基础也能看懂

    (原创)超详细一步一步在eclipse中配置Struts2环境,无基础也能看懂 1. 在官网https://struts.apache.org下载Struts2,建议下载2.3系列版本.从图中可以看出 ...

  6. 移动端解决单机事件延迟fastclick

    引入百度静态公共资源库 <script type='application/javascript' src='http://apps.bdimg.com/libs/fastclick/1.0.0 ...

  7. 浏览器各个版本和系统(chrome/safari/edge/qq/360)

    浏览器对象: let userAgent = navigator.userAgent.toLowerCase()console.log(userAgent) Edge: mozilla/5.0 (wi ...

  8. CentOS7.4使用KVM

    参考地址 [root@node1 ~]# cat /etc/centos-release CentOS Linux release 7.4.1708 (Core) [root@node1 ~]# un ...

  9. P1273 有线电视网

    题目描述 某收费有线电视网计划转播一场重要的足球比赛.他们的转播网和用户终端构成一棵树状结构,这棵树的根结点位于足球比赛的现场,树叶为各个用户终端,其他中转站为该树的内部节点. 从转播站到转播站以及从 ...

  10. SkylineGlobe 7.0.1 & 7.0.2版本Web开发 如何正确使用三维地图控件和工程树控件

    Skyline TerraExplorer Pro目前正式发布的7.0.1&7.0.2版本,还只是64位的版本, 在Web开发的时候,如何在页面中正确嵌入三维地图控件,让一些小伙伴凌乱了. 下 ...