转自:http://www.cnblogs.com/icyJ/p/migration.html

准备工作

1.新建一个控制台项目, 在"程序包管理控制台"执行 Install-package EntityFramework  //安装EF环境

2.在项目下新建类(Paper),也就是code first中的code。建好之后,Ctrl+Shift+B生成项目。(不生成的话,会出现控制器找不到类型或者其他报错)

3.在app.config或web.config的configuration下添加节点connectionStrings:

<connectionStrings>
<add name="DefaultConnection" connectionString="Data Source=.;Initial Catalog=MySite;Persist Security Info=True;User ID=a;Password=b" providerName="System.Data.SqlClient" />
</connectionStrings>

4.项目下新建类SiteDbContext,作为项目的数据上下文:

public class SiteDbContext : DbContext
{
public SiteDbContext() : base("DefaultConnection") { }
public DbSet<Paper> Papers { get; set; }
}

在类下定义构造函数,传递步骤3的connectionString的name给基类构造函数。这样,数据的获取就会通过步骤3的数据库链接了。同时在数据上下文中定义已经定义好的类的DbSet类型的属性。为后面的迁移做准备。

增表

1.此时,如果直接在program的Main函数中调用SiteDbContext,然后操作下面的Papers数据,会在数据库自动生成Papers表。调试程序。

2.打开迁移:Enable-Migrations

Checking if the context targets an existing database...
Detected database created with a database initializer. Scaffolded migration '201502150256371_InitialCreate' corresponding to existing database. To use an automatic migration instead, delete the Migrations folder and re-run Enable-Migrations specifying the -EnableAutomaticMigrations parameter.
Code First Migrations enabled for project MigrationTest.

执行完命令后,在项目中自动生成文件夹Migrations,以及文件夹下面的Configuration.cs和201502150256371_InitialCreate.cs

增属性

1.修改类Paper的结构,在这里,我们新增属性public string Test{get;set;},生成程序。

2.为了验证数据库会不会全部重新生成,我们在数据库里手动插入几条数据:

3.增加迁移的节点:Add-Migration PaperTest(在前面操作的基础上,执行这条命令时,程序会自动判断在上次迁移基础上的修改)

执行完上面的命令后,会在文件夹Migrations下自动生成一个类:

public partial class PaperTest : DbMigration
{
public override void Up()
{
AddColumn("dbo.Papers", "Test", c => c.String());
} public override void Down()
{
DropColumn("dbo.Papers", "Test");
}
}

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

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

4.执行Update-Database,将这里的修改升级到数据库。

查看提示,在Update命令后面输入参数-Verbose可以查看升级的明细。

第二行,运行迁移对象201502260053423_PaperTest。

第三行,运行Seed函数。这里说明一下,Seed函数在Configuration.cs里面:

protected override void Seed(MigrationTest.SiteDbContext 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. E.g.
//
// context.People.AddOrUpdate(
// p => p.FullName,
// new Person { FullName = "Andrew Peters" },
// new Person { FullName = "Brice Lambson" },
// new Person { FullName = "Rowan Miller" }
// );
//
}

仔细查看注释的语句,可以看到,这个函数在每次迁移到最新版本时调用。用AddOrUpdate函数可以避免生成重复的数据。最后面给了一个AddOrUpdate的调用示例。

这个函数的用处,我暂时理解为,生成初始化数据。不管怎么迁移,都会存在这些数据。

5.执行完上面的操作后,再回到数据库,查看数据结构和数据内容:

 

到此,在现有的类上面增加属性的操作完成了。

删属性

删除属性的操作和增加属性的操作差不多。首先修改类结构,屏蔽上面的//public string Test { get; set; }。然后Add一个迁移节点,命名为DelPaperTest。执行此命令,生成相应的迁移类文件。最后执行Update-Database,在这里我们用Update-Database -Verbose命令,查看一下执行的详细内容:

PM> Update-Database -Verbose
Using StartUp project 'MigrationTest'.
Using NuGet project 'MigrationTest'.
Specify the '-Verbose' flag to view the SQL statements being applied to the target database.
Target database is: 'MySite' (DataSource: ., Provider: System.Data.SqlClient, Origin: Configuration).
Applying explicit migrations: [201502260118534_DelPaperTest].
Applying explicit migration: 201502260118534_DelPaperTest.
DECLARE @var0 nvarchar(128)
SELECT @var0 = name
FROM sys.default_constraints
WHERE parent_object_id = object_id(N'dbo.Papers')
AND col_name(parent_object_id, parent_column_id) = 'Test';
IF @var0 IS NOT NULL
EXECUTE('ALTER TABLE [dbo].[Papers] DROP CONSTRAINT [' + @var0 + ']')
ALTER TABLE [dbo].[Papers] DROP COLUMN [Test]
INSERT [dbo].[__MigrationHistory]([MigrationId], [ContextKey], [Model], [ProductVersion])
VALUES (N'201502260118534_DelPaperTest', N'MigrationTest.SiteDbContext', 0x1F8...00 , N'6.1.2-31219') Running Seed method.

查看上面内容里面的sql语句,首先寻找列Test相关的约束,如果有,先删除约束。然后删除列,最后在迁移历史表里面写入一行迁移记录。

改属性

1.在Paper类下修改属性名称,生成项目:

public string Desc { get; set; }  -->  public string DescAA { get; set; }

2.按照常规的方法,接下来我们应该添加一个迁移的节点。首先我们看看这样执行有什么样的结果:

Add-Migration ModifyPaper

打开自动生成的迁移类文件201502260128314_ModifyPaper.cs:

public partial class ModifyPaper : DbMigration
{
public override void Up()
{
AddColumn("dbo.Papers", "DescAA", c => c.String());
DropColumn("dbo.Papers", "Desc");
} public override void Down()
{
AddColumn("dbo.Papers", "Desc", c => c.String());
DropColumn("dbo.Papers", "DescAA");
}
}

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

3.执行Update-Database的结果如下:

如何才能在保留现有数据的基础上修改列名呢?

(常规操作中,不建议类似这样修改列名的操作,因为数据库的调用可能不止这一处,容易产生漏改而出现bug)

注意:修改列名见下面的方法三。下面的内容已过时,留文仅作记录。

1.直接修改类属性Desc为DescAA,同时,手动修改数据库列名为DescAA。运行程序,会报错:

2.在运行程序前,删除迁移文件夹Migrations。然后运行程序,同样报上面的错误。

3.项目中执行命令Enable-Migrations,重新生成迁移文件夹。然后运行程序,同样报错。

4.删除数据库中迁移历史表中的项目相关的迁移记录,同时删除项目中的Migrations文件夹,然后再执行Enable-Migrations,会看到:

同时Migrations文件夹下除了Configuration.cs,没有任何其他的类文件。

到此,修改类结构的属性名称完成,同时成功保住了数据库的现有数据。

但是此方法,有一个陷阱。

如果在修改属性之后,又有增属性或者删属性的操作,在Add-Migration之后,自动生成的类里面,会出现这样的代码:

public partial class DelTestAfterChangeDescAA : DbMigration
{
public override void Up()
{
CreateTable(
"dbo.Papers",
c => new
{
PaperID = c.Int(nullable: false, identity: true),
PaperName = c.String(),
DescAA = c.String(),
})
.PrimaryKey(t => t.PaperID); } public override void Down()
{
DropTable("dbo.Papers");
}
}

上面的代码直接CreateTable和DropTable。这是执行Update-Database会提示失败,因为数据库已有表Papers

这时,我们可以选择手动的修改Up和Down的内容:

public partial class DelTestAfterChangeDescAA : DbMigration
{
public override void Up()
{
DropColumn("dbo.Papers", "Test"); } public override void Down()
{
AddColumn("dbo.Papers", "Test", c => c.String());
}
}

执行Update-Database,命令完成。

方法二(注意:修改列名见下面的方法三。下面的内容已过时,留文仅作记录。):

1.在上面的基础上,修改Paper类的DescAA为Desc。

2.运行Add-Migration ModifyDescAA,得到迁移cs文件,手动注释其中Up的DropColumn

public partial class ModifyDesc : DbMigration
{
public override void Up()
{
AddColumn("dbo.Papers", "Desc", c => c.String());
//DropColumn("dbo.Papers", "DescAA");
} public override void Down()
{
//AddColumn("dbo.Papers", "DescAA", c => c.String());
DropColumn("dbo.Papers", "Desc");
}
}

3.执行Update-Database。这时,数据库的Papers表新增列Desc。

4.进入数据库,手动删除刚才新增的Desc列,同时,将DescAA列名修改成Desc。

5.运行程序,可以调试,说明上面的修改属性名操作成功。

6.为了防止以后迁移到某个特定的版本时,回滚出现问题。手动屏蔽上面2步骤中Up和Down中的代码.

这里留意:不能手动删除迁移历史表中的刚才一行迁移历史,同时手动删除项目中上面2步骤生成的cs文件。这样会直接报上面的"数据库上下文已改"错。

上面这两种方法,操作完了之后都需要做一定工作量的修补,否则下面的Code first就会有些隐患。

第三种方法

在调试完上面两种方法后,发现DbMigration有RenameColumn的函数。

呵呵,在这个函数的基础上,修改属性名称就变得超级简单了。

1.修改Paper的DescAA,改成Desc

2.执行Add-Migration RenameDesc命令,生成迁移类文件,手动修改类文件内容如下:

public partial class RenameDesc : DbMigration
{
public override void Up()
{
//AddColumn("dbo.Papers", "Desc", c => c.String());
//DropColumn("dbo.Papers", "DescAA");
RenameColumn("dbo.Papers", "DescAA", "Desc");
} public override void Down()
{
//AddColumn("dbo.Papers", "DescAA", c => c.String());
//DropColumn("dbo.Papers", "Desc");
RenameColumn("dbo.Papers", "Desc", "DescAA");
}
}

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

这里值得注意的是,在执行Update命令时,程序会提醒操作着,修改列名可能会导致存储过程及其他调用列的sql脚本失效:

这是在实际操作中要注意的问题,也正是笔者不建议随便修改列名的主要原因——可能导致其他调用失效。

笔者小记:

边摸索边操作,到这里,对EF的code first架构算是有了一定的了解

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

2.在数据库的迁移历史表中,字段Model有一些加了密的迁移映射,随意删除修改会导致"数据库上下文被改"的错误。

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

理解了上面的这些点,简单使用以code first为基础的EF,应该没什么问题了。

Top            
推荐            
收藏            
关注            
评论            
 

EF code First数据迁移学习笔记(转)的更多相关文章

  1. EF code First数据迁移学习笔记

    准备工作 1.新建一个控制台项目, 在"程序包管理控制台"执行 Install-package EntityFramework  //安装EF环境 2.在项目下新建类(Paper) ...

  2. EF Code First 数据迁移配置

    这里我想讲清楚code first 数据迁移的两种模式,还有开发环境和生产环境数据迁移的最佳实践. 1.1 数据迁移综述 EF Code first 虽然已经有了几种不同的数据库初始化策略,但是大部分 ...

  3. EF Code First 数据迁移操作

    打开执行命令窗体 1.EF Code First创建数据库 PM> Install-Package EntityFramework 2.EF Code First数据库迁移 2.1.生成数据库 ...

  4. MVC 使用EF Code First数据迁移之添加字段

    PM> add-migration 20161109   -Force 正在为迁移“20161109”搭建基架.此迁移文件的设计器代码包含当前 Code First 模型的快照.在下一次搭建迁移 ...

  5. EF Code First 数据迁移命令

    只需要开启程序管理控制台(Package Manager Console) 然后输入  Enable-Migrations -ContextTypeName youContextdb(你的数据库上下文 ...

  6. 解决 MVC4 Code First 数据迁移 数据库发生更改导致调试失败解决方法(二)

    文章转载自:http://www.cnblogs.com/amoniyibeizi/p/4486617.html 前几天学MVC过程中,遇到更改Model类以后,运行程序就会出现数据已更改的问题导致调 ...

  7. 图文详解 解决 MVC4 Code First 数据迁移

    在使用Code first生成数据库后 当数据库发生更改时 运行程序就会出现数据已更改的问题  这时可以删除数据库重新生成解决 但是之前的数据就无法保留  为了保留之前的数据库数据  我们需要使用到C ...

  8. Code First 数据迁移 转

    一.为模型更改设置 Code First 数据迁移 1.工具—>库程序包管理器—>程序包管理器控制台—>输入“Enable-Migrations”  或者 Enable-Migrat ...

  9. EF架构~CodeFirst数据迁移与防数据库删除

    回到目录 本文介绍两个概念,防数据库自动删除,这是由于在code first模式下,当数据实体发生变化时,会对原来数据库进行删除,并将新数据表添加进来,但这对于我们的运营环境数据库,是万万不能接受的, ...

随机推荐

  1. gradle研究

    gradle介绍:http://www.oschina.net/p/gradle gradle官网:https://gradle.org gradle的  eclipse 插件:http://www. ...

  2. 转 自定义View之onMeasure()

    可以说重载onMeasure(),onLayout(),onDraw()三个函数构建了自定义View的外观形象.再加上onTouchEvent()等重载视图的行为,可以构建任何我们需要的可感知到的自定 ...

  3. WebService学习总结(二)——WebService相关概念介绍

    一.WebService是什么? 1. 基于Web的服务:服务器端整出一些资源让客户端应用访问(获取数据) 2. 一个跨语言.跨平台的规范(抽象) 3. 多个跨平台.跨语言的应用间通信整合的方案(实际 ...

  4. debian7 请把标有“Debian GNU/Linux 7.1.0 _Wheezy_ - Official amd64 DVD Binary-1 20130615-23:06”的盘片插入驱动器“/media/cdrom/”再按回车键

    有时候,在通过apt-get install 安装软件的时候,会出现: 更换介质:请把标有“Debian GNU/Linux 7.1.0 _Wheezy_ - Official amd64 DVD B ...

  5. 编写一个Java程序,计算半径为3.0的圆周长和面积并输出结果。把圆周率π定义为常量,半径定义为变量,然后进行计算并输出结果。

  6. jQuery Form 表单提交插件-----formSerialize,fieldSerialize,fieldValue,resetForm,clearForm,clearFields的 应用

    一.jQuery Form的其他api  1.  formSerialize 将表单序列化成查询串.这个方法将返回一个形如: name1=value1&name2=value2的字符串.是否可 ...

  7. Eclipse修改Tomcat发布路径以及的配置多个Tomcat方法

    最近放弃了使用Myeclipse,转而使用eclipse作为开发工具,确实Myeclipse集成了太多东西,使得开发人员的配置越来越少,这 不是个好事,使用eclipse后,有些地方就得自己去配置,比 ...

  8. 烂泥:KVM虚拟机克隆

    本文由秀依林枫提供友情赞助,首发于烂泥行天下. 上一篇文章介绍了有关KVM虚拟机快照的创建与恢复,这篇文章我们来介绍有关KVM虚拟机克隆. KVM虚拟机的克隆,我们可以分以下几步: 1. 使用virt ...

  9. yum 安装包的用法

    最近刚爆出linux下glibc有重大漏洞,修复方案为升级glibc库 RHEL/CentOS下一键即可修复 : sudo yum update glibc .或者如果本地有rpm包 直接 rpm - ...

  10. Hadoop blocks

    一In cases where the last record in a block is incomplete, the input split includes location informat ...