但数据库Schema产生变化时EF会须要大家做

引言

在EntityFramework的支出进度中大家有时因急需变动依然数据结构划设想计的变型平时会改变表结构。但数据库Schema产生变化时EF会供给我们做DataMigration
UpdateDatabase。但在这几个进程中怎样才能保险现有数据库的数额存在。

别的本文只针对CodeFirst的方法来做。

 

创设早先模型和数据库

准备3个简练的 EFCodeFirst 德姆o

 

  • 始建叁个控制台程序 MigrationsDemo
  • NuGet 获取最新版 EntityFramework 
    • Tools –> Library Package Manager –> Package Manager
      Console
    • Run the Install-Package EntityFramework command

图片 1

  • 添加 Model.cs文件. 定义三个 Blog 类作为大家的政工模型
    并为其添加 BlogContext 使用 EF (Code First )模式的DataContext

 

using System.Data.Entity;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Data.Entity.Infrastructure;

namespace MigrationsDemo
{
    public class BlogContext : DbContext
    {
        public DbSet<Blog> Blogs { get; set; }
    }

    public class Blog
    {
        public int BlogId { get; set; }
        public string Name { get; set; }
    }
}

在Program.cs文件中不难演示下如何利用大家刚刚定义好的业务类和DataContext。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace MigrationsDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            using (var db = new BlogContext())
            {
                db.Blogs.Add(new Blog { Name = "Another Blog " });
                db.SaveChanges();

                foreach (var blog in db.Blogs)
                {
                    Console.WriteLine(blog.Name);
                }
            }

            Console.WriteLine("Press any key to exit...");
            Console.ReadKey();
        }
    }
}

心急的运作下我们的小程序:

图片 2

运维程序后大家能够查阅下EF为大家自行创立的MigrationsCodeDemo.BlogContext
数据库:

If SQL Express is installed (included in Visual Studio 2010) then the
database is created on your local SQL Express instance
(.\SQLEXPRESS). If SQL Express is not installed then Code First
will try and use LocalDb ((localdb)\v11.0) – LocalDb is included
with Visual Studio 2012.
Note: SQL Express will always get precedence if it is installed,
even if you are using Visual Studio 2012

 

图片 3

图片 4

 

  在起头选拔迁移(Migrations)以前,大家须要二个 Project 和一个 Code
First Model
, 对于本文将运用典型的 Blog 和 Post 模型

启用 Migration

目前自家想为大家的 Blog 类扩张1个UPRADOL属性。

在Blog类扩张如下一行代码:

public string Url { get; set; }

再次运转大家的次第!

Ops…出难题呀!!

图片 5

 

If you were to run the application again you would get an
InvalidOperationException stating The model backing the ‘BlogContext’
context has changed since the database was created. Consider using
Code First Migrations to update the database
(
http://go.microsoft.com/fwlink/?LinkId=238269).

 

基于极度消息提醒,大家要为DataContext启用Migrations

  • 在Package Manager Console 窗口中 运营命令 Enable-Migrations

图片 6图片 7

运转完命令后我们会意识Project树中多了3个 Migrations folder to our
project, this new folder contains two files:

  • The Configuration class. 那么些类用于自定义Migration的行为.
    那里我们接纳暗中同意Configuration.
    大家项目中只是三个简短的 Code First context , Enable-Migrations
    自动将context type 应用到 configuration 的泛型类型参数.
  • An InitialCreate migration.
    因为大家在启用migration以前已经有Code First
    数据库,所以就会变动这几个migration。 那几个migration
    的代码表示了数据库中已部分 objects . 在该例中 正是 Blog 表有
    BlogIdName 两列.
    文件名中蕴藏1个时光戳,那样有利于大家排序。

If the database had not already been created this InitialCreate
migration would not have been added to the project. Instead, the first
time we call Add-Migration the code to create these tables would be
scaffolded to a new migration.

假诺刚先河没有开创数据库,InitialCreate  migration将会在首先次施行
Add-Migration 命令时生成。

 

  • 开创二个新的控制台应用程序 *MigrationsDemo;*
  • 加上最新的 EntityFramework 到项目
    • Tools –> Library Package Manager –> Package Manager
      Console
      ;
    • 运维命令 Install-Package EntityFramework  
  • *  创建 **Blog.cs 和 DbContext 的派生类 BlogContext.cs***

    public class Blog
    {

    public int BlogId { get; set; }
    public string Name { get; set; }
    

    }

    public class BlogContext : DbContext
    {

    public DbSet<Blog> Blogs { get; set; }
    

    }

同二个数据库同时对应多个Model

When using versions prior to EF6, only one Code First model could be
used to generate/manage the schema of a database. This is the result
of a single __MigrationsHistory table per database with no way
to identify which entries belong to which model.

Starting with EF6, the Configuration class includes a
ContextKey property. This acts as a unique identifier for each
Code First model. A corresponding column in the
__MigrationsHistorytable allows entries from multiple models to
share the table. By default, this property is set to the fully
qualified name of your context.

 

  更改 Program.cs 以调用

何以转变和运维Migration

 

Code First Migrations 有多少个重要的下令供给熟知.

  • Add-Migration
    协会根据上次Migration后的满贯修改生成此次的Migration。
  • Update-Database 将拥有挂起(未履行)的migration应用到数据库。

 

我们转移的Migration须要留意添加了个新的Url属性,Add-Migration 
允许大家给Migration 名字,那里笔者钦赐为 AddBlogUrl.

  • 在Package Manager Console 中执行 Add-Migration AddBlogUrl 命令
  • 在Migrations文件夹中生成了1个 AddBlogUrl
    migration.并且自动为名字添加了个时间戳,方便大家排序。

    namespace MigrationsDemo.Migrations
    {

    using System;
    using System.Data.Entity.Migrations;
    
    public partial class AddBlogUrl : DbMigration
    {
        public override void Up()
        {
            AddColumn("dbo.Blogs", "Url", c => c.String());
        }
    
        public override void Down()
        {
            DropColumn("dbo.Blogs", "Url");
        }
    }
    

    }

 

咱俩得以编写制定这几个 migration,但那里大家无需做别的改动 .该是使用
Update-Database 将Migration应用到数量库.

  • 在Package Manager Console 运行 Update-Database 命令
  • Code First Migrations 将把Migrations
    文件夹中的Migration于已经选用到数据库中Migration实行相比。
    最后我们会看出AddBlogUrl 将会被应用数据库.

最终 MigrationsDemo.BlogContext 数据库中的Blogs表会扩张 Url
列.

 

图片 8

自定义 Migration

到如今任务 大家转变并实行了二个尚无做任何改动的Migration.
未来大家看下如何通过修改自动生成的代码落成自定义Migration.

  • Blog 添加 Rating 属性

    public int Rating { get; set; }

大家扩大一个Post类

public class Post
{
    public int PostId { get; set; }
    [MaxLength(200)]
    public string Title { get; set; }
    public string Content { get; set; }

    public int BlogId { get; set; }
    public Blog Blog { get; set; }
}

 

  • Blog 类扩充3个 Posts collection
    属性来集团Blog和Post的关系

    public virtual List Posts { get; set; }

 

作者们将用Add-Migration 生成 migration,并取名为AddPostClass.

  • 在Package Manager Console运行 Add-Migration AddPostClass .

Code First Migrations在共青团和少先队修改时确实做的没错, 但小编依然想做点修改:

  1. 首先 为 Posts.Title 列扩大1个unique index
  2. 扩充非空驶列车 Blogs.Rating .
    假如数额表中已经有数据,会给新增的该列一个CL哈弗中该品种的暗许值(因为Rating
    是integer所以设为 0),但大家想为已经存在的多少,设置Rating
    暗许值为3 .

    namespace MigrationsDemo.Migrations
    {

    using System;
    using System.Data.Entity.Migrations;
    
    public partial class AddPostClass : DbMigration
    {
        public override void Up()
        {
            CreateTable(
                "dbo.Posts",
                c => new
                    {
                        PostId = c.Int(nullable: false, identity: true),
                        Title = c.String(maxLength: 200),
                        Content = c.String(),
                        BlogId = c.Int(nullable: false),
                    })
                .PrimaryKey(t => t.PostId)
                .ForeignKey("dbo.Blogs", t => t.BlogId, cascadeDelete: true)
                .Index(t => t.BlogId)
                .Index(p => p.Title, unique: true);
    
            AddColumn("dbo.Blogs", "Rating", c => c.Int(nullable: false, defaultValue: 3));
        }
    
        public override void Down()
        {
            DropIndex("dbo.Posts", new[] { "Title" });
            DropIndex("dbo.Posts", new[] { "BlogId" });
            DropForeignKey("dbo.Posts", "BlogId", "dbo.Blogs");
            DropColumn("dbo.Blogs", "Rating");
            DropTable("dbo.Posts");
        }
    }
    

    }

 

咱俩修改migration来知足我们的要求 ,运营Update-Database
来升级数据库到新型版本. 我们得以由此点名 –Verbose 看到
SQL的实市价况.

  • 在 Package Manager Console运行 Update-Database –Verbose .

 

 

static void Main(string[] args)
{
    using (var db = new BlogContext())
    {
        db.Blogs.Add(new Blog { Name = "Another Blog" });
        db.SaveChanges();

        foreach (var blog in db.Blogs)
        {
            Console.WriteLine(blog.Name);
        }
    }

    Console.WriteLine("Press any key to exit...");
    Console.ReadKey();
}

Migration进度中的数据迁移|自定义SQL

到近日大家精晓了到Migration的操作不会修改数据也不会转换数据到新数据库,以往就让我们看下怎么样搬运大家的数额,那里没有原生帮忙,但大家得以在经过在钦点的地方执行任意想要的SQL脚本来实现大家的想法。

添加 Post.Abstract 属性. 稍后大家将用
Content的内容来扭转Abstract .

public string Abstract { get; set; }

我们将用 Add-Migration 命令让Code First Migrations
为大家转移最接近大家想要migration.

  • 在Package Manager Console运行 Add-Migration AddPostAbstract
    命令.
  • 变化的migration 注意到schema
    的变型,但没能完成用Post的前九二十个字符content 来填充Abstract 列.
    小编可以通过SQL 运转UPDATE 命令,在创建Abstract 列.
    (Adding in line 12 in the code below)

    namespace MigrationsDemo.Migrations
    {

    using System;
    using System.Data.Entity.Migrations;
    
    public partial class AddPostAbstract : DbMigration
    {
        public override void Up()
        {
            AddColumn("dbo.Posts", "Abstract", c => c.String());
    
            Sql("UPDATE dbo.Posts SET Abstract = LEFT(Content, 100) WHERE Abstract IS NULL");
        }
    
        public override void Down()
        {
            DropColumn("dbo.Posts", "Abstract");
        }
    }
    

    }

笔者们修改migration来满足大家的急需 ,运转Update-Database
来升级数据库到新型版本. 大家得以因而点名 –Verbose 看到
SQL的执行情况.

  • 在 Package Manager Console运行 Update-Database –Verbose .

 

 

图片 9

将数据库更新到钦点的版本Migration(包含进步 ,降级或然说是回滚)

到方今截至我们已经得以将数据库更新到最新版本Migration,但神跡需求升高或降职到内定的Migration.

现在有个分外情状想让数据库回到运转完AddBlogUrl
migration的情状。那事大家就能够动用–TargetMigration
来降级数据库到该版本

  • 在Package Manager Console 运行Update-Database –TargetMigration:
    AddBlogUrl
    命令.

该命令将会运营  AddBlogAbstractAddPostClass migration的
Down脚本 .

假诺想再次回到最初 Update-Database –TargetMigration: $InitialDatabase
那条命令将会帮您一步到位.

 

 

  运转查看结果

获取Migration的SQL 脚本

一经其余二个开发人士想要应用大家对数据库的改动,他能透过Source Control
获取自笔者签入的摩登代码,一旦他有了流行代码就能够通过Update-Database
将持有修改应用到地头。然则有时我们想把大家的改动发表到测试服务器甚至生产条件中,那样我们恐怕就要求一份能够交给DBA的SQL脚本。

  • 运行Update-Database 的同时内定 –Script
    那样就只会生成脚本而不是行使Migration。我们也能够钦定Migration的Source和Target。eg.
    从空数据库 ($InitialDatabase) 到最新版本(migration
    AddPostAbstract).
    If you don’t specify a target migration, Migrations will use the
    latest migration as the target. If you don’t specify a source
    migrations, Migrations will use the current state of the
    database.(固然没有点名目标版本,将会私下认可设置Target到最新版本Migration,倘诺没有钦命源,将默许将最近数据库的气象设置为Source)
  • 在Package Manager Console中Update-Database -Script
    -SourceMigration: $InitialDatabase -TargetMigration:
    AddPostAbstract

 

Code First Migrations
将会把实际要运用的修改生成2个.sql文件而不是运用到数据库。一旦SQL脚本生成VisualStudio会自动打开该脚本,你可以挑选是或不是保存。

图片 10

Generating Idempotent Scripts (EF6 onwards)

Starting with EF6, if you specify –SourceMigration
$InitialDatabase
then the generated script will be ‘idempotent’.
Idempotent scripts can upgrade a database currently at any version to
the latest version (or the specified version if you use
–TargetMigration). The generated script includes logic to check
the __MigrationsHistory table and only apply changes that
haven’t been previously applied.

 

  发现如上错误“CREATE DATABSE permission denied in databse ‘master'”

应用程序运营时自动升级数据库导最新版本

在布置程序后,假使想在先后运转时自动升级数据库(通过使用Migration),你能够经过挂号MigrateDatabaseToLatestVersion
database initializer来完结该目标. 它是1个大约的 database initializer
但能有限支撑数据库正确升级到新型版本. This logic is run the first time the
context is used within the application process (AppDomain).

修改下Program.cs 如下示,
BlogContext设置MigrateDatabaseToLatestVersion initializer .
注意须求引入 System.Data.Entity 命名空间

When we create an instance of this initializer we need to specify the
context type (BlogContext) and the migrations configuration
(Configuration) – the migrations configuration is the class that
got added to our Migrations folder when we enabled Migrations.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Entity;
using MigrationsDemo.Migrations;

namespace MigrationsDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            Database.SetInitializer(new MigrateDatabaseToLatestVersion<BlogContext, Configuration>());

            using (var db = new BlogContext())
            {
                db.Blogs.Add(new Blog { Name = "Another Blog " });
                db.SaveChanges();

                foreach (var blog in db.Blogs)
                {
                    Console.WriteLine(blog.Name);
                }
            }

            Console.WriteLine("Press any key to exit...");
            Console.ReadKey();
        }
    }
}

近期大家的主次就足以在运行时,自动将数据库升级到新型版本啦。

 

源码下载
MigrationsDemo.rar

 

  我们在 BlogContext 上的无参构造函数上添加诊断代码并设置调节和测试断点

参考

Code First
Migrations

Code First Migrations in Team
Environments

Entity Framework 6 中 Code First
的好处

System.Diagnostics.Debug.Write(Database.Connection.ConnectionString);

Entity Framework 6 Code First Migrations with Multiple Data Contexts

  再度运营

Understanding Entity Framework Code First Migrations

图片 11

  大家注意到 Data
Scource
 竟然是 .\\SQLEXPRESS 而不是我们想要的 localDB ,
那是因为:

  • 假诺大家设置了 SQL Express,那么 database 将会安装在 local SQL
    Express instance,
    否则 Code First 才将尝试利用 localDB;
  • SQL Express 总是有着优先权,只要安装了它

  知道了原委大家就好消除了:

  再一次运维就行了,让大家看一下后台生成的数据库

图片 12

 

启用迁移

  大家对模型 Blog 做一些改变:增添三个 Url 属性 

public string Url { get; set; }

  我们那儿再度运维程序,发现如下错误

图片 13

  ‘InvalidOperationException’ was unhandled. The model backing the
‘BlogContext’ context has changed since the database was created.
Consider using Code First Migrations to update the database
( [http://go.microsoft.com/fwlink/?LinkId=238269*](http://go.microsoft.com/fwlink/?LinkId=238269)*)**

  正如错误音讯提醒的那么,是时候使用 Code First
Migrations,
第2步是运维如下的指令:

  • 在 Package Manager Console 下运作命令 Enable-Migrations

图片 14

 

图片 15

  这几个命令将在档次下创办理文件件夹 *Migrations *

  • The Configuration
    class 
    以此类允许你去安顿哪些迁移,对于本文将选择暗许的计划(在本文中因为唯有三个 ContextEnable-Migrations 将机关对 context
    type 
    作出适配);
  • An InitialCreate
    migration
     
    (本文为 201312240822431_InitialCreate.cs)这几个迁移之所以存在是因为大家事先用 Code
    First
     制造了数据库, 在启用迁移前,scaffolded
    migration
     里的代码表示在数据库中曾经创办的目的,本文中即为表 Blog (列 BlogId 和 Name).
    文件名蕴含3个 timestamp 以便排序(假若在此以前数据库没有被创立,那么 InitialCreate
    migration 
    将不会被创建,相反,当大家率先次调用 Add-Migration 的时候全体表都将归集到八个新的 migration 中)

 

多少个实体锁定同一数据库

  当使用 EF6 以前的本辰时,只会有二个 Code First
Model
 被用来变化/管理数据库的 Schema,
那将招致每一个数据库只会有一张 *__MigrationsHistory *表,从而不可能辨认实体与模型的对应关系。

   从 EF6 开始,*Configuration 类将会含有二个 **ContextKey 性格,它将用作每1个 Code
First
Model 的绝无仅有标识符, 
__MigrationsHistory* 表中1个应和地的列允许来自多少个模型(multiple
models
)的实体共享表(entries),暗中认可景况下那脾性子被设置成 context 的一点一滴限定名。

 

浮动、运维迁移

  Code First Migrations 有五个你要求熟谙的通令:

  •  Add-Migration 将 scaffold 成立下一回基于上1遍迁移以来的更动的搬迁;
  • *Update-Databse *将此外挂起的动员搬迁应用到数据库

  大家必要脚手架(scaffold 直译)3个搬迁,以地点的 Url 属性为例,命令 Add-Migration 允许大家对搬迁命名,大家权且称之为 AddBlogUrl 

  • 在 Package Manager
    Console
     中运作命令 *Add-Migration** AddBlogUrl;*
  • 1个新的迁徙(名称包罗 timestamp 前缀)在目录 Migrations 中创设成功

图片 16

 

图片 17

图片 18

namespace MigrationsDemo.Migrations
{
    using System;
    using System.Data.Entity.Migrations;

    public partial class AddBlogUrl : DbMigration
    {
        public override void Up()
        {
            AddColumn("dbo.Blogs", "Url", c => c.String());
        }

        public override void Down()
        {
            DropColumn("dbo.Blogs", "Url");
        }
    }
}

图片 19

  大家未来能够对那些迁移实行编写制定或许扩张,但如同看起来尚可,那大家就径直用 Update-Database 来利用到数据库吧

  • 在 Package Manager Console 中运转命令 *Update-Database** *;
  • *AddBlogUrl 搬迁将会被使用到数据库(表 Blogs 扩充一列 Url*)

图片 20

 

图片 21

 

定制化迁移

  到近期停止大家转变并运营了三个搬迁,不过并未对搬迁做任何改变,下边我们将尝试做一些改观:在类 Bolg 上加码一属性 Rating

public int Rating { get; set; }

  新建 Post

图片 22

public class Post
{
    public int PostId { get; set; }
    [MaxLength(200)]
    public string Title { get; set; }
    public string Content { get; set; }

    public int BlogId { get; set; }
    public Blog Blog { get; set; }
}

图片 23

  在 *Blog 中添加 **Post ***的集合

public virtual ICollection<Post> Posts { get; set; }

  在 Package Manager Console 中运作命令 Add-Migration
AddPostClass

  生成的迁徙如下

图片 24

图片 25

namespace MigrationsDemo.Migrations
{
    using System;
    using System.Data.Entity.Migrations;

    public partial class AddPostClass : DbMigration
    {
        public override void Up()
        {
            CreateTable(
                "dbo.Posts",
                c => new
                    {
                        PostId = c.Int(nullable: false, identity: true),
                        Title = c.String(maxLength: 200),
                        Content = c.String(),
                        BlogId = c.Int(nullable: false),
                    })
                .PrimaryKey(t => t.PostId)
                .ForeignKey("dbo.Blogs", t => t.BlogId, cascadeDelete: true)
                .Index(t => t.BlogId);

            AddColumn("dbo.Blogs", "Rating", c => c.Int(nullable: false));
        }

        public override void Down()
        {
            DropForeignKey("dbo.Posts", "BlogId", "dbo.Blogs");
            DropIndex("dbo.Posts", new[] { "BlogId" });
            DropColumn("dbo.Blogs", "Rating");
            DropTable("dbo.Posts");
        }
    }
}

图片 26

  接下去大家对搬迁做些更改:

  • 在 Posts.Title 列上扩大唯一索引;
  • 使 Blogs.Rating 列非空,对于表中已经存在的数量,新列都会被赋值成 CLR 的暗许数据类型(如 Rating 是整型,故暗中同意值为0),可是大家想钦赐默许值为3,那样存在的笔录将会有叁个理所当然的评分。

  更改后的代码如下

图片 27

namespace MigrationsDemo.Migrations
{
    using System;
    using System.Data.Entity.Migrations;

    public partial class AddPostClass : DbMigration
    {
        public override void Up()
        {
            CreateTable(
                "dbo.Posts",
                c => new
                    {
                        PostId = c.Int(nullable: false, identity: true),
                        Title = c.String(maxLength: 200),
                        Content = c.String(),
                        BlogId = c.Int(nullable: false),
                    })
                .PrimaryKey(t => t.PostId)
                .ForeignKey("dbo.Blogs", t => t.BlogId, cascadeDelete: true)
                .Index(t => t.BlogId)
                .Index(p => p.Title, unique: true);

            AddColumn("dbo.Blogs", "Rating", c => c.Int(nullable: false, defaultValue: 3));
        }

        public override void Down()
        {
            DropIndex("dbo.Posts", new[] { "Title" });
            DropForeignKey("dbo.Posts", "BlogId", "dbo.Blogs");
            DropIndex("dbo.Posts", new[] { "BlogId" });
            DropColumn("dbo.Blogs", "Rating");
            DropTable("dbo.Posts");
        }
    }
}

图片 28

  在 Package Manager Console 中运营命令 Update-Database
–Verbose

图片 29

图片 30

 

数量移动 / 定制SQL 

  迄今截至,迁移都并未改变或移动多少,以后让我们看一下索要活动数据的例证。即使尚未对数码移动的原生援救,可是大家得以任意运转 SQL 脚本。

  让大家在 Post 中加进一个属性 Abstract,
稍后大家采用列 Content 的起始来填充此列(数据库已有记录) 

public string Abstract { get; set; }
  • 在 Package Manager Console 中运转命令 Add-Migration
    AddPostAbstract**
     **;
  • 扭转的搬迁卓殊好,可是我们想接纳 Content 的前 100
    个字符来预填充 Abstract 列,我们可对搬迁做如下改变

图片 31

namespace MigrationsDemo.Migrations
{
    using System;
    using System.Data.Entity.Migrations;

    public partial class AddPostAbstract : DbMigration
    {
        public override void Up()
        {
            AddColumn("dbo.Posts", "Abstract", c => c.String());
            Sql("UPDATE dbo.Posts SET Abstract = LEFT(Content, 100) WHERE Abstract IS NULL");
        }

        public override void Down()
        {
            DropColumn("dbo.Posts", "Abstract");
        }
    }
}

图片 32

  在 Package Manager Console 中运转命令 Update-Database
–Verbose

 

搬迁至钦命版本(包罗后退)

  迄今甘休,大家连年升级至最新迁移,不过一些时候大家要求升级/降级至钦点版本,例如大家想迁移数据库至运转 *AddBlogUrl *迁移之后的意况,此时我们就足以应用 –TargetMigration 来降级到那一个本子

  在 Package Manager Console 中运维命令 Update-Database
–TargetMigration: AddBlogUrl
 

图片 33

  这几个命令将会运作 *AddBlogAbstract and **AddPostClass **的 Down* 命令

  假若您想回滚一切至空数据库,能够行职责令 Update-Database
–TargetMigration: $InitialDatabase

 图片 34

 

得到SQL脚本

  借使别的开发人士也希望在他们友善的机械上独具那么些改动,他们只需在我们 check
in
 代码至 source
control
 的时候做3回联袂即可,一旦他们持有了那几个迁移,只需运维命令 Update-Database 就能够把那么些改动应用于地面。可是只要大家想把这一个改变推送至测试服务器或生产服务器,大家或者要求一份 SQL 脚本提要求 DBA

  • 在运行 Update-Database 的时候钦赐-Specify 标记,大家就可知使得那些改动被写入一个剧本中而不是被运用,大家还要也会为此脚本钦赐源迁移和对象迁移,例如咱们盼望产生的脚本是从八个空数据库($InitialDatabase)到新型的版本(AddPostAbstract 搬迁);(注意:假如您没有点名目的迁移,那么迁移将始终立异至最新版本;尽管你从未钦命源迁移,那么迁移将以数据库近来情景为伊始)
  • 在 Package Manager Console 中运维命令 Update-Database -Script
    -SourceMigration: $InitialDatabase -TargetMigration:
    AddPostAbstract

图片 35

  产生的 SQL 脚本如下

图片 36

图片 37

DECLARE @CurrentMigration [nvarchar](max)

IF object_id('[dbo].[__MigrationHistory]') IS NOT NULL
    SELECT @CurrentMigration =
        (SELECT TOP (1) 
        [Project1].[MigrationId] AS [MigrationId]
        FROM ( SELECT 
        [Extent1].[MigrationId] AS [MigrationId]
        FROM [dbo].[__MigrationHistory] AS [Extent1]
        WHERE [Extent1].[ContextKey] = N'MigrationsDemo.BlogContext'
        )  AS [Project1]
        ORDER BY [Project1].[MigrationId] DESC)

IF @CurrentMigration IS NULL
    SET @CurrentMigration = '0'

IF @CurrentMigration < '201312240822431_InitialCreate'
BEGIN
    CREATE TABLE [dbo].[Blogs] (
        [BlogId] [int] NOT NULL IDENTITY,
        [Name] [nvarchar](max),
        CONSTRAINT [PK_dbo.Blogs] PRIMARY KEY ([BlogId])
    )
    CREATE TABLE [dbo].[__MigrationHistory] (
        [MigrationId] [nvarchar](150) NOT NULL,
        [ContextKey] [nvarchar](300) NOT NULL,
        [Model] [varbinary](max) NOT NULL,
        [ProductVersion] [nvarchar](32) NOT NULL,
        CONSTRAINT [PK_dbo.__MigrationHistory] PRIMARY KEY ([MigrationId], [ContextKey])
    )
    INSERT [dbo].[__MigrationHistory]([MigrationId], [ContextKey], [Model], [ProductVersion])
    VALUES (N'201312240822431_InitialCreate', N'MigrationsDemo.BlogContext',  0x1F8B0800000000000400CD574B4FDB4010BE57EA7FB0F6D41EC826E1D22207040954511B4018B86FEC4958751FAE778D92DFD6437F52FF4267FD8E4D1E200EBD44F178E69B996FE7B1FEFBFB8F7FB692C27B86C470AD4664D0EB130F54A823AE962392DAC5D1177276FAF1837F19C995F758EA1D3B3DB45466449EAC8D4F2835E11348667A928789367A617BA19694459A0EFBFDAF7430A0801004B13CCFBF4B95E512B2077C1C6B15426C5326663A02610A39BE093254EF9A4930310B6144667C99308B519809484DBC73C11946118058108F29A56DF6F6E4C1406013AD96418C0226EED731A0DE82090345EC27B5FAA169F4872E0D5A1BBE8906522588295E221576EDC2CBD21C910BA1974D0DD4F90EEB0D018A6E131D4362D777B068D84D23E2D14D5BDA36AE4C5B762E8411992A7B3C24DE752A049B0BA8186B501B589DC03750800701D12DB3161264701A41964A2782963FF75B7AC323C24A23DE8CAD7E805ADA273C60B622DE155F41544A8A081E14C7C244239BA4B0CFC94322DED9874FEB93EA9E1F96B0651C296990EA64B0B2ADB3CCF503B00D4D43BC1A3C2FE65E56062F4650F9AAFB84E68D523614DDD251FE8CC53192D1E8B042E205797B8D8F82D797B4CC3168685EA8EC2ADACA13960F5B42EB2DBAC648AF7862EC84593667EE38C691ECA81DC06CE9A94970BB7F6ABE4B6DF73FB7D89C31BD6E433699BBC26424567E96175431BCD4C785611032C1922D5D38D622956A5747EF42C97BAB89914B0E47C81AA7099009BAF63E6DE5DF269876186ECDA5F671EDAAF4B64AE5BDAAF85665FB4595ED5F289DB2CB558887C43CF3C8955CB0361664CF29F4825F622C38E65B2BCC98E20B30F65EFF049C83C3FE60D8DA4B6FD811D49848FCCF8B823B0AF6AE82CE1E397C37A86796844F2CF924D9EA7313E995F3FF1538AF9BF1DD81B57FD26F1DF479D58D4834C74BCD7D1E60B11ADEB803BA1DE0D3E6C5CB9F80E1CB1AC25DC314846EEED5A0A5CE542D74493166D48CA854699DC00C2C8B9098F3C4F2050B2DBE0EC1986C153F3291A2CAA59C43345537A98D537B6E0CC8B9D8B83EF874B7FF6CD16DC6ECDFC4D9E47E8F14304C8E29C08DBA48B988AAB8AFBAA5BC0DC2D548D11F18155E45106EB9AE90AEB53A10A8A06F023128D75DF720638160E64605EC19B6C7B69FC34DC6FC0967B8FEA429306A7BF71D40DD87C0E93F1D45E2A93A0C0000 , N'6.0.2-21211')
END

IF @CurrentMigration < '201312310618077_AddBlogUrl'
BEGIN
    ALTER TABLE [dbo].[Blogs] ADD [Url] [nvarchar](max)
    INSERT [dbo].[__MigrationHistory]([MigrationId], [ContextKey], [Model], [ProductVersion])
    VALUES (N'201312310618077_AddBlogUrl', N'MigrationsDemo.BlogContext',  0x1F8B0800000000000400CD574B4FDB4010BE57EA7FB0F6D41EC826E1D22207040954511B4018B86FEC4958751FAE778D92DFD6437F52FF4267FD8E4D1E200EBD44F178E69B996FE7B1FEFBFB8F7FB692C27B86C470AD4664D0EB130F54A823AE962392DAC5D1177276FAF1837F19C995F758EA1D3B3DB45466449EAC8D4F2835E11348667A928789367A617BA19694459A0EFBFDAF7430A0801004B13CCFBF4B95E512B2077C1C6B15426C5326663A02610A39BE093254EF9A4930310B6144667C99308B519809484DBC73C11946118058108F29A56DF6F6E4C1406013AD96418C0226EED731A0DE82090345EC27B5FAA169F4872E0D5A1BBE8906522588295E221576EDC2CBD21C910BA1974D0DD4F90EEB0D018A6E131D4362D777B068D84D23E2D14D5BDA36AE4C5B762E8411992A7B3C24DE752A049B0BA8186B501B589DC03750800701D12DB3161264701A41964A2782963FF75B7AC323C24A23DE8CAD7E805ADA273C60B622DE155F41544A8A081E14C7C244239BA4B0CFC94322DED9874FEB93EA9E1F96B0651C296990EA64B0B2ADB3CCF503B00D4D43BC1A3C2FE65E56062F4650F9AAFB84E68D523614DDD251FE8CC53192D1E8B042E205797B8D8F82D797B4CC3168685EA8EC2ADACA13960F5B42EB2DBAC648AF7862EC84593667EE38C691ECA81DC06CE9A94970BB7F6ABE4B6DF73FB7D89C31BD6E433699BBC26424567E96175431BCD4C785611032C1922D5D38D622956A5747EF42C97BAB89914B0E47C81AA7099009BAF63E6DE5DF269876186ECDA5F671EDAAF4B64AE5BDAAF85665FB4595ED5F289DB2CB558887C43CF3C8955CB0361664CF29F4825F622C38E65B2BCC98E20B30F65EFF049C83C3FE60D8DA4B6FD811D49848FCCF8B823B0AF6AE82CE1E397C37A86796844F2CF924D9EA7313E995F3FF1538AF9BF1DD81B57FD26F1DF479D58D4834C74BCD7D1E60B11ADEB803BA1DE0D3E6C5CB9F80E1CB1AC25DC314846EEED5A0A5CE542D74493166D48CA854699DC00C2C8B9098F3C4F2050B2DBE0EC1986C153F3291A2CAA59C43345537A98D537B6E0CC8B9D8B83EF874B7FF6CD16DC6ECDFC4D9E47E8F14304C8E29C08DBA48B988AAB8AFBAA5BC0DC2D548D11F18155E45106EB9AE90AEB53A10A8A06F023128D75DF720638160E64605EC19B6C7B69FC34DC6FC0967B8FEA429306A7BF71D40DD87C0E93F1D45E2A93A0C0000 , N'6.0.2-21211')
END

IF @CurrentMigration < '201312310648099_AddPostClass'
BEGIN
    CREATE TABLE [dbo].[Posts] (
        [PostId] [int] NOT NULL IDENTITY,
        [Title] [nvarchar](200),
        [Content] [nvarchar](max),
        [BlogId] [int] NOT NULL,
        CONSTRAINT [PK_dbo.Posts] PRIMARY KEY ([PostId])
    )
    CREATE INDEX [IX_BlogId] ON [dbo].[Posts]([BlogId])
    CREATE UNIQUE INDEX [IX_Title] ON [dbo].[Posts]([Title])
    ALTER TABLE [dbo].[Blogs] ADD [Rating] [int] NOT NULL DEFAULT 3
    ALTER TABLE [dbo].[Posts] ADD CONSTRAINT [FK_dbo.Posts_dbo.Blogs_BlogId] FOREIGN KEY ([BlogId]) REFERENCES [dbo].[Blogs] ([BlogId]) ON DELETE CASCADE
    INSERT [dbo].[__MigrationHistory]([MigrationId], [ContextKey], [Model], [ProductVersion])
    VALUES (N'201312310648099_AddPostClass', N'MigrationsDemo.BlogContext',  0x1F8B0800000000000400D558CD6EE33610BE17E83B083AB505D64AB29736B07791759222681D0751B2D78091C60E518A54452AB09F6D0F7DA4BE4287FA33454AB6ECAC17DD4B1093331F6786DF0C67F4EF977FC61F5709F35E219354F0897F3A3AF13DE09188295F4EFC5C2DDEFDEA7FFCF0E30FE3AB3859799F6BB9F75A0E35B99CF82F4AA5E74120A31748881C2534CA84140B358A4412905804672727BF05A7A70120848F589E37BECFB9A209143FF0E754F0085295133613313059ADE34E58A07AB7240199920826FE8C2E33A2D00A790989F0BD0B46095A11025BF81EE15CA862F7FC5142A832C197618A0B843DAC5340B90561122ADBCF37E243DD3839D36E041BC583C2E0370EA28B57180AB5D6E6156E4EFC4F4C2C4D0994F903D6AD055CBACB440A995ADFC3C2D0BB897D2F68EB06B672A36AE9691326FE0D57EFCF7CEF36678C3C336822668436542283DF81035E04C4774429C83082373114AE381658E7E9BFF5697845C834DF9B91D59FC097EA052F98AC7CEF9AAE20AE572A0B1E394562A292CA72D875C863C68E7EC63D8643036F0F9C85714B5EE9B288A3857627A492BE770FACA4F70B4D4B5A8FF4CE53C10AEF3A13C9BD609578B1F8F440B225283443D83BA1C8B3C832611C6C08B795861AE6101A6ABD436858EB7D2B1A3E50C5B6F110F3F52B70044B9B427B8ECEC561493C948B25D9F6A7624D38978A35498750F1424A11D1E268831B4F1D75F18AC75EAF0D65C06BAB31E63953346534C22327FE2F4E34BAC09ADCDA8095DEB7C14E7D3B2FE6FC121828F02EA2F27D99121991D8BD038C41DC5EC154824C739830648F5419A15CB97947794453C2FA4CB614F67831B4510DBCBD730929709D617D717FDBB90DBC15A45D3119070669DCB2A6B3103520330C2832736597B8523E0465486255DE10B5C50287416DE5AAA43BCA251F2D65C3813642956FC6BE938C761CB7E5456364639F730DDB32C150AF626313BAED4847BE37B7B1E9F382B2D1AB1BC2A0A7231CCF489A6201353AC46AC50BCBF670FA2EDCBF254B4A8C20921D9D59636D7312BE3B6409D6AE2EF5315CD34CAA4BA2C833D1F5761A278ED800EED527991474EFA826552DADFF2F35DA3DF2A88B229BC85DA333894EE8E23DB5AED7552B9A72C248D6F3004D05CB13BE3DCFFB51CADED0C428578623148D9F09502C0CD7AF9B3A13A25E7351C6811545A7A239F7E494FFF6A50FA24499B86FA084DBDC0DA244B75A5F28EB8ECE0C657777B80DA5EAD34C906A693846D3859928CDE2709CFD487E547238C5D416694E6F8AAA553CC75521DB3D733B95AD14F13D0CCF2B8D75550BD7524132D202A3F06F3665B4086D2D30239C2E40AA07F11770DD5B9F9E59A3FB0163742065CCFECFB334D521D839A6ECEAD2B78CCFFC9564D10BC97E4AC8EA671369CF11F94D38ED31B8F079AB4BDFC9047A94CB6B0D9D75D4DDB173BF0BB066CC375D6607810FBACC4366B8B2CFFD96A356BBD13D60663C6856EBE9C78E369F7D1F3399DB3EEF9ECC7A07B3F2819AF8F1B3C05B2DD9DB3DAE74CD6CBD235B176CE71075A469CEF479D3A3EF1AE09C99EF38339BDB4E20478C0FFDC84D49971B08FDD99F43D462472373C317A226A965512D6255AE19281223752E3245172452B81D8194C5D3F499B01C45AE9267886FF83C5769AED065489E59EB3BA126FBB6F38BC1B46DF3789E166DF5D77001CDA4E802CCF9A79CB2B8B1FBBAA3EEF640E82CAADE2B7D974ABF5BCB7583742BF840A02A7C4DF23F4092320493731E9257E8B76D770CDB111B5F5282B349222B8C8D3EFE44FAC5C9EAC37FEC5F9589AA1A0000 , N'6.0.2-21211')
END

IF @CurrentMigration < '201312310729575_AddPostAbstract'
BEGIN
    ALTER TABLE [dbo].[Posts] ADD [Abstract] [nvarchar](max)
    UPDATE dbo.Posts SET Abstract = LEFT(Content, 100) WHERE Abstract IS NULL
    INSERT [dbo].[__MigrationHistory]([MigrationId], [ContextKey], [Model], [ProductVersion])
    VALUES (N'201312310729575_AddPostAbstract', N'MigrationsDemo.BlogContext',  0x1F8B0800000000000400D559CD6EE33610BE17E83B083AB505D64AB29736B077E1759222689D0451B2D78096C636518A54452AB09F6D0F7DA4BE4287FA1729D9B2B35E742F414CCE7C9C197E339CB1FFFDF2CFF8E32662CE2B24920A3E71CF4767AE033C1021E5AB899BAAE5BB5FDD8F1F7EFC617C1D461BE77329F75ECBA126971377AD547CE97932584344E428A24122A458AA5120228F84C2BB383BFBCD3B3FF700215CC4729CF163CA158D20FB801F67820710AB94B0B90881C9621D77FC0CD5B92311C898043071E77495108556C82B8884EB4C192568850F6CE93A8473A1B2DDCB6709BE4A045FF9312E10F6B48D01E5968449286CBFACC587BA7176A1DDF06AC5A3C2E0560EA28BD7180AB5D5E6656E4EDC4F4CAC9A1228F3076C5B0BB8F490881812B57D846543EF36741DAFADEB99CA95AAA1A74D98B8B75CBDBF709DBB9431B2605045AC115A5F89047E070E7811103E10A520C108DE8690B96259609CA7FF96A7E11521D35C674E367F025FA9355E30D9B8CE0DDD4058AE14163C738AC4442595A4B0EF90E7849DFC8C470C8706DE1D3803E38EBCD255164703ED4148255DE711584EEF358D735A8FF4CE4BC60AE72611D1A3608578B6F8F2449215283443983BBE4893C03061ECD584DB49430D730C0DB5DE31342CF5BE150D9FA862BB7888F9FA153882A54DA13D27E7E27421554282D31F34AC5A0C257DCEEAC3395F32DBE67C990D43383F955204343BBA41C2978E027CCD43A7D7863CE0A5D518F394291A331AE09113F7172B1A5D605512D760B9F76DB073D74CC07B7E050C1438D3207FC866440624B4EF006310B657306721D1C94218D254F38772652738E5018D09EB33D95038E069D24655F0E6CE15C4C0752AF7C5FD6DE756F04690F6C564EC354863D74F9DEEA80149C380AC046CCC5A9ACBFBA01A9258FE6BA2B6586031A8AD5CBC1D9672CE4743B9E1401BA1C8B7C6BE958C661C77E5456564659F750DBB32A1A15EC4C62474DB918E7CAF6EA36E28BDBCA32C3B4FAFA7F51CCF491C63016DB4A2C58AE3E77DE8EC9D7F78EF17E5185E203B5AC0CADAEA247CE0C80A8C5DFDA684704313A9AE88220BA2EBED2C8C2CB101DC2B4F6A52D0BEA39254A5B4FE3FD76837E3A32E8AD491BB4167229DD0D9C36D5CAFAD9675FF8491A4E7019A0996467C779EF7A3E44D6813235F198E9075984D806C61B87ED93D3621CA351B65EC1951B42A9A754F56F96F5FFA204AE489FB064AD85DE4204A74ABF585B26C1D9BA1EC6E4377A1140D6113A4581A8E51B57B4D946A71384EDDCE3581EAD5E14887A5CB496966956553A43ABD2ACF46191E172571FFD704568DCC455C07C3F34A435D1FFDAD54108DB4C0C8FF9BCD18CD2EA91498134E9720D593F80BB81E07CE2F8C6F1B8E98FC3D2943F67F1EFFA90EC1DEC96A5FBFBF63E2E7AF2409D624F929229B9F9B48074EF56FC2694FEE99CF3B5DFA4E86E6935C5E6B4E2EA36E4FCA875D803116BFE932CDD1F74D601DD97014338E192DF3F6FB5B4E80EDFEFB8851F6A811B2A74D3CD9D8F87D8C8A7657BF7F60EC9D17F3D76EE2860B81B79AB3B77B8AEA1A257B27C92ED8CED9EE444366D3E77A74D837575AA3E8694649BB37418E347EE8406E4ABAAA21F4CF1E1C82163B2A995BBE1425490D8B4A11A372CD419110A9334D145D6239C4ED00A4CCDEB9CF84A528721D2D20BCE5F7A98A53852E43B460ADEF4935D9779D9FCDCB6D9BC7F771D6ED7F0D17D04C8A2EC03DFF9452165676DF74D4DD1E089D45C5E3A7EF52E94770B5AD90EE041F085484AF4AFE2788628660F29EFBE415FA6DDB1FC376C4C65794E0C814C902A3D6C78F48BF30DA7CF80FF7E621BAAA1B0000 , N'6.0.2-21211')
END

图片 38

 

爆发幂等剧本(EF6+)

  从 EF6 初步,假若您利用 –SourceMigration
$InitialDatabase
, 发生的本子将是幂等的,幂等脚本意味着无论数据库当前处于什么版本/状态,都能进步至最新版本或内定版本(指定 TargetMigration),生成的本子包括检查表 *__MigrationsHistory *的逻辑以及只更新在此之前从未更新的

 

在应用程序运转时自动升级(MigrateDatabaseToLatestVersion开始化器)

  当您公布计划应用程序的时候,可能希望当程序运转的时候它自动更新数据库(更新应用任何未更新的动员搬迁),你能够通过注册 MigrateDatabaseToLatestVersion 数据库初阶化器来兑现这点,数据库开始化器只含有部分逻辑检查用于确认保证数据库被正确安装,这一个逻辑检查将会在AppDomain 的 context 第叁次被运用的时候实施。

  当我们成立1个初步化器的实例时,要求钦赐 context
type
BlogContext)以及 migrations
configuration 
Configuration)-
这几个迁移配置类是在我们启用迁移时生成的 *Migrations *目录下扩大的

图片 39

图片 40

using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MigrationsDemo.Migrations;

namespace MigrationsDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            Database.SetInitializer(new MigrateDatabaseToLatestVersion<BlogContext, Configuration>());

            using (var db = new BlogContext())
            {
                db.Blogs.Add(new Blog { Name = "Another Blog " });
                db.SaveChanges();

                foreach (var blog in db.Blogs)
                {
                    Console.WriteLine(blog.Name);
                }
            }

            Console.WriteLine("Press any key to exit...");
            Console.ReadKey();
        }
    }
}

图片 41

原文:http://msdn.microsoft.com/en-us/data/jj591621

转自:http://www.cnblogs.com/panchunting/p/entity-framework-code-first-migrations.html

相关文章