众所周知当我们的项目涉及到数据库时,随着需求或大或小的 变更后,我们之前设计好的数据模型会发生部分的更改,导致数据表、或者数据字段的增加、修改等,这个时候我们就需要对数据库结构进行修改,如果我们之前采用codefirst方式生成数据模型,我们如何进行数据结构的更改,这里不得不提EF6的数据迁移功能。

“迁移”是一组有序的步骤,描述如何升级(和降级)数据库架构。这些步骤(称为“迁移”)中的每个步骤均包含一些代码,用于描述要应用的更改。

假如我们需要在Stuednt类增加一个新的字段(我们继续接着使用上一节的例子),我们在Student类中增加一个字段PhoneNumber。

public class Student
{
public int ID { get; set; } public string Name { get; set; } public string Class { get; set; } public int Age { get; set; } public string PhoneNumber { get; set; }
}

接着我们启动控制台程序,继续录入我们Student信息。结果我们发现程序报错,在增加学生实体时报错---The model backing the 'EntityClassContext' context has changed since the database was created. Consider using Code First Migrations to update the database (http://go.microsoft.com/fwlink/?LinkId=238269),提示在数据库创建后实体模型改变了,请考虑使用CodeFirst 迁移更新数据库。

那么我们如何再CodeFirst模式下进行数据迁移呢,首先第一步我们需要为模型启用 Code First 迁移。打开Nuget程序包管理器控制台,输入启用迁移命令---Enable-Migrations

在工具----Nuget程序包管理器----程序包管理器控制台--输入命令Enable-Migrations

一个新的 Migrations 文件夹已添加至项目中,它包含两个文件:
       Configuration.cs —这个类允许你去配置如何迁移,对于本文将使用默认的配置。
       <时间戳>_InitialCreate.cs — 这个迁移之所以存在是因为我们之前用 Code First 创建了数据库, 在启用迁移前,scaffolded migration 里的代码表示在数据库中已经创建的对象,本文中即为表 Student. 文件名包含一个 timestamp 以便排序(如果之前数据库没有被创建,那么 InitialCreate migration 将不会被创建,相反,当我们第一次调用 Add-Migration 的时候所有表都将归集到一个新的 migration 中)

Code First Migrations 有两个你需要熟悉的命令:

Add-Migration 将 创建下一次基于上一次迁移以来的更改的迁移;
      Update-Databse 将任何挂起的迁移应用到数据库
以上面的 Student 类为例,我们增加了一个PhoneNumber字段,这样我们需要使用到迁移功能,命令 Add-Migration 允许我们对迁移命名,我们姑且称之为 AddPhoneNumber,即Add-Migration AddPhoneNumber---对迁移命名,我们可以通过命名来了解此次我们对数据模型做了哪些更改。

在Nuget程序包控制台中运行命令 Add-Migration AddPhoneNumber;一个新的迁移(名称包含 timestamp 前缀)在目录 Migrations 中创建成功,该类记录了我们对数据模型做了什么更改。我们可以通过这个文件对数据模型进行还原等其他的操作,这个我们后面再说。

在程序包管理器控制台中运行 Update-Database 命令。此命令将所有挂起的迁移应用于数据库,因此这些迁移将应用新的 AddPhoneNumber迁移。

提示:在调用 Update-Database 命令查看对数据库执行的 SQL 时,可以使用 –Verbose 开关。

然后我们打开数据库查看我们的表结构是否增加了字段PhoneNumber,我们打开SqlService管理器,表Student查看。确实已经增加了字段PhoneNumber。

到目前为止我们总是将数据库模型迁移至最新模式,假如某一次你修改了某张表的数据格式--增加了字段或者删除了字段,并且将他们迁移了,然而随后你又发现你需要将数据模型迁移会之前的某个时间节点,这个时候我们需要用到数据迁移的回迁功能。(所以我们最好在每次的更改数据模型的时候 使用Add-Migration 保存上一次的数据模型配置 )。

刚才我们为student类增加了一个PhoneNumber属性,现在我们需要将其迁回至最初的状态。我们可以使用命令Update-Database –TargetMigration: name

在 Nuget程序包控制台中运行命令 Update-Database –TargetMigration: InitialCreate即可迁回至最初的状态(这个状态是指启用迁移前的状态,如果数据库有数据,数据会保留)。

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

如果其它开发人员也希望在他们自己的机器上拥有这些更改,他们只需在我们 check in 代码至 source control 的时候做一次同步即可,一旦他们拥有了这些迁移,只需运行命令 Update-Database 就可以把这些更改应用于本地。但是如果我们想把这些更改推送至测试服务器或生产服务器,我们也许需要一份 SQL 脚本提供给 DBA

在运行 Update-Database 的时候指定 -Specify 标记,我们就能够使得这些更改被写入一个脚本中而不是被应用,我们同时也会为此脚本指定源迁移和目标迁移,例如我们希望产生的脚本是从一个空数据库($InitialDatabase)到最新的版本(AddPhoneNumber 迁移);(注意:如果你没有指定目标迁移,那么迁移将始终更新至最新版本;如果你没有指定源迁移,那么迁移将以数据库目前状态为初始)
在 Nuget控制台中运行命令 Update-Database -Script -SourceMigration: $InitialDatabase -TargetMigration: AddPhoneNumber 。运行成功后我们会得到一顿sql脚本。我们将得到的脚本保存在sqlserver中运行。会得到状态为AddPhoneNumber时的数据库状态。

从 EF6 开始,如果你使用 –SourceMigration $InitialDatabase, 产生的脚本将是幂等的,幂等脚本意味着无论数据库当前处于什么版本/状态,都能升级至最新版本或指定版本(指定 –TargetMigration),生成的脚本包括检查表 __MigrationsHistory 的逻辑以及只更新之前从未更新的

当然有时我们不想建立数据库模型的各个状态变化,我们想做的是所做即所得---即我们做了什么更改数据模型就是什么状态。

你可以通过注册 MigrateDatabaseToLatestVersion 数据库初始化器来实现这一点,数据库初始化器只包含一些逻辑检查用于确保数据库被正确设置,这个逻辑检查将会在AppDomain 的 context 第一次被使用的时候执行。

  当我们创建一个初始化器的实例时,需要指定 context type('EntityClassContext' )以及 migrations configuration (Configuration)- 这个迁移配置类是在我们启用迁移时生成的 Migrations 目录下增加的

我们在程序开头假如这句代码。

Database.SetInitializer(new MigrateDatabaseToLatestVersion<EntityClassContext, Configuration>());

同时将Configuration类中的自动启用迁移设为true,   AutomaticMigrationsEnabled =true。

下节我们将介绍一下 EF CodeFirst 约定、注释及Fluent API。这也是CodeFirst比较重要的部分。

Entity Framework CodeFirst------数据迁移(二)的更多相关文章

  1. Entity Framework CodeFirst数据迁移

    前言 紧接着前面一篇博文Entity Framework CodeFirst尝试. 我们知道无论是“Database First”还是“Model First”当模型发生改变了都可以通过Visual ...

  2. Entity Framework Migrations 数据迁移

    在使用Entity Framework 过程中,经常会遇到需要变更model 的状况,此时可以使用Migrations ,将每次变更记录以便后续更换机器或是运行在生产环境,持久层可保持一致. 在Pac ...

  3. Entity Framework Code First 迁移

    Entity Framework CodeFirst数据迁移 http://www.cnblogs.com/aehyok/p/3325459.html Entity Framework Code Fi ...

  4. entity framework codefirst 用户代码未处理DataException,InnerException基础提供程序在open上失败,数据库生成失败

    警告:这是一个入门级日志,如果你很了解CodeFirst,那请绕道 背景:这篇日志记录我使用Entity FrameWork CodeFirst时出现的错误和解决问题的过程,虽然有点曲折……勿喷 备注 ...

  5. 第二篇:Entity Framework CodeFirst & Model 映射

    前一篇 第一篇:Entity Framework 简介 我有讲到,ORM 最关键的 Mapping,也提到了最早实现Mapping的技术,就是 特性 + 反射,那Entity Framework 实现 ...

  6. EF Code-First数据迁移

    Code-First数据迁移  首先要通过NuGet将EF升级至最新版本. 新建MVC 4项目MvcMigrationDemo 添加数据模型 Person 和 Department,定义如下: usi ...

  7. 【EF】EF Code-First数据迁移

    Code-First数据迁移  首先要通过NuGet将EF升级至最新版本. 新建MVC 4项目MvcMigrationDemo 添加数据模型 Person 和 Department,定义如下: usi ...

  8. 第三篇:Entity Framework CodeFirst & Model 映射 续篇 EntityFramework Power Tools 工具使用

    上一篇 第二篇:Entity Framework CodeFirst & Model 映射 主要介绍以Fluent API来实作EntityFramework CodeFirst,得到了大家一 ...

  9. Entity Framework Codefirst的配置步骤

    Entity Framework Codefirst的配置步骤: (1) 安装命令: install-package entityframework (2) 创建实体类,注意virtual关键字在导航 ...

  10. ADO.NET Entity Framework CodeFirst 如何输出日志(EF 5.0)

    ADO.NET Entity Framework CodeFirst 如何输出日志(EF4.3) 用的EFProviderWrappers ,这个组件好久没有更新了,对于SQL执行日志的解决方案的需求 ...

随机推荐

  1. Android Context作用

    Context 用于访问全局信息的接口 App的资源: strings, drawable资源等等 工程代码:LearnContext.zip ---------------------------- ...

  2. Python学习 - 使用BeautifulSoup来解析网页一:基础入门

    写技术博客主要就是总结和交流的,如果文章用错,请指正啊! 以前一直在使用SGMLParser,这个太费时间和精力了,现在为了毕业设计,改用BeautifulSoup来实现HTML页面的解析工作的. 一 ...

  3. python中去掉空行的问题

    在python中处理空行时,经常会遇到一些问题.现总结经验如下: 1.遇到的空行如果只有换行符,直接使用=='\n'或者 len(line)==line.count('\n') 2.有多个空格+换行符 ...

  4. 在 LINQ to Entities 查询中无法构造实体或复杂类型

    public List<CustomerType> GetCustomerTypesBySchemaTypeCode(int schemaTypeCode) { var query = ( ...

  5. SharePoint 2013 如何使用TaxonomyWebTaggingControl 控件

    在该文章中,我将介绍如何使用TaxonomyWebTaggingControl控件, 首先我相信您已经在SharePoint Managed Metadata Service里定义Term Sets, ...

  6. BZOJ 1207 打鼹鼠

    Description 鼹鼠是一种很喜欢挖洞的动物,但每过一定的时间,它还是喜欢把头探出到地面上来透透气的.根据这个特点阿Q编写了一个打鼹鼠的游戏:在一个n*n的网格中,在某些时刻鼹鼠会在某一个网格探 ...

  7. int 和String之间的互转

    int -> String int i=12345;String s="";第一种方法:s=i+"";第二种方法:s=String.valueOf(i); ...

  8. 获取Delphi所有类的类信息

    Delphi遍历进程中所有Class的TypeInfo,即便是在implementation中的class或者其他 class的private的子class. 一般普通EXE中的TypeInfo存放在 ...

  9. 12.HTML编辑器(CKEditor、CKFinder集成)

    CKEditor原名为FckEditor,是著名的HTML编辑器,可以在线编辑HTML内容. 配置参考文档:主要将ckeditor中的lang.plugins.skins.ckeditor.js.co ...

  10. MySQL 没有索引 锁全表

    <h3 class="title" style="box-sizing: inherit; margin: 8px 0px 15px; padding: 0px; ...