创建初始模型和数据库

  在开始使用迁移(Migrations)之前,我们需要一个 Project 和一个 Code First Model, 对于本文将使用典型的 BlogPost 模型

  • 创建一个新的控制台应用程序 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; }
}

  更改 Program.cs 以调用

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();
}

  运行查看结果

  发现如上错误"CREATE DATABSE permission denied in databse 'master'"

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

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

  再次运行

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

  • 如果我们安装了 SQL Express,那么 database 将会安装在 local SQL Express instance,否则 Code First 才将尝试使用 localDB;
  • SQL Express 总是具有优先权,只要安装了它

  知道了原因我们就好解决了:

  • 如果想继续使用 SQL Express,那么就配置相应地权限,请参考 http://odetocode.com/Blogs/scott/archive/2012/08/14/a-troubleshooting-guide-for-entity-framework-connections-amp-migrations.aspx;
  • 如果想改用 localDB, 只需在.config 配置即可(放在 configSections 节点后面)
  <connectionStrings>
<add name="BlogContext" connectionString="Data Source=(LocalDb)\v11.0;Initial Catalog=BlogContext;Integrated Security=SSPI;" providerName="System.Data.SqlClient"/>
</connectionStrings>

  再次运行就行了,让我们看一下后台生成的数据库

启用迁移

  我们对模型 Blog 做一些更改:增加一个 Url 属性

public string Url { get; set; }

  我们此时再次运行程序,发现如下错误

  '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)

  正如错误消息提示的那样,是时候使用 Code First Migrations,第一步是运行如下的命令:

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

  这个命令将在项目下创建文件夹 Migrations 

  • The Configuration class 这个类允许你去配置如何迁移,对于本文将使用默认的配置(在本文中因为只有一个 Context, Enable-Migrations 将自动对 context type 作出适配);
  • An InitialCreate migration (本文为 201312240822431_InitialCreate.cs)这个迁移之所以存在是因为我们之前用 Code First 创建了数据库, 在启用迁移前,scaffolded migration 里的代码表示在数据库中已经创建的对象,本文中即为表 Blog (列 BlogIdName). 文件名包含一个 timestamp 以便排序(如果之前数据库没有被创建,那么 InitialCreate migration 将不会被创建,相反,当我们第一次调用 Add-Migration 的时候所有表都将归集到一个新的 migration 中)

多个实体锁定同一数据库

  当使用 EF6 之前的版本时,只会有一个 Code First Model 被用来生成/管理数据库的 Schema, 这将导致每个数据库只会有一张 __MigrationsHistory 表,从而无法辨别实体与模型的对应关系。

   从 EF6 开始,Configuration 类将会包含一个 ContextKey 属性,它将作为每一个 Code First Model 的唯一标识符, __MigrationsHistory 表中一个相应地的列允许来自多个模型(multiple models)的实体共享表(entries),默认情况下这个属性被设置成 context 的完全限定名。

生成、运行迁移

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

  • Add-Migration 将 scaffold 创建下一次基于上一次迁移以来的更改的迁移;
  • Update-Databse 将任何挂起的迁移应用到数据库

  我们需要脚手架(scaffold 直译)一个迁移,以上面的 Url 属性为例,命令 Add-Migration 允许我们对迁移命名,我们姑且称之为 AddBlogUrl

  • Package Manager Console 中运行命令 Add-Migration AddBlogUrl;
  • 一个新的迁移(名称包含 timestamp 前缀)在目录 Migrations 中创建成功

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");
}
}
}

  我们现在可以对这个迁移进行编辑或者增加,但似乎看起来还不错,那我们就直接用 Update-Database 来应用到数据库吧

  • 在 Package Manager Console 中运行命令 Update-Database ;
  • AddBlogUrl 迁移将会被应用到数据库(表 Blogs 增加一列 Url

定制化迁移

  到目前为止我们生成并运行了一个迁移,但是没有对迁移做任何更改,下面我们将尝试做一些更改:在类 Bolg 上增加一属性 Rating

public int Rating { get; set; }

  新建 Post

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

  在 Blog 中添加 Post 的集合

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

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

  生成的迁移如下

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: ),
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");
}
}
}

  接下来我们对迁移做些更改:

  • 在 Posts.Title 列上增加唯一索引;
  • 使 Blogs.Rating 列非空,对于表中已经存在的数据,新列都会被赋值成 CLR 的默认数据类型(如 Rating 是整型,故默认值为0),但是我们想指定默认值为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: ),
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: ));
} 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");
}
}
}

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

数据移动 / 定制SQL 

  迄今为止,迁移都没有更改或移动数据,现在让我们看一下需要移动数据的例子。虽然没有对数据移动的原生支持,但是我们可以随意运行 SQL 脚本。

  让我们在 Post 中增加一个属性 Abstract, 稍后我们使用列 Content 的开头来填充此列(数据库已有记录)

public string Abstract { get; set; }
  • 在 Package Manager Console 中运行命令 Add-Migration AddPostAbstract ;
  • 生成的迁移非常好,但是我们想使用 Content 的前 100 个字符来预填充 Abstract 列,我们可对迁移做如下更改
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");
}
}
}

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

迁移至指定版本(包括后退)

  迄今为止,我们总是升级至最新迁移,然而某些时候我们需要升级/降级至指定版本,例如我们想迁移数据库至运行 AddBlogUrl 迁移之后的状态,此时我们就可以使用 –TargetMigration 来降级到这个版本

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

  这个命令将会运行 AddBlogAbstract and AddPostClass Down 命令

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

得到SQL脚本

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

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

  产生的 SQL 脚本如下

DECLARE @CurrentMigration [nvarchar](max)

IF object_id('[dbo].[__MigrationHistory]') IS NOT NULL
SELECT @CurrentMigration =
(SELECT TOP ()
[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 = '' 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]() NOT NULL,
[ContextKey] [nvarchar]() NOT NULL,
[Model] [varbinary](max) NOT NULL,
[ProductVersion] [nvarchar]() 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](),
[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
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, ) 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

产生幂等脚本(EF6+)

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

在应用程序启动时自动升级(MigrateDatabaseToLatestVersion初始化器)

  当你发布部署应用程序的时候,可能希望当程序启动的时候它自动更新数据库(更新应用任何未更新的迁移),你可以通过注册 MigrateDatabaseToLatestVersion 数据库初始化器来实现这一点,数据库初始化器只包含一些逻辑检查用于确保数据库被正确设置,这个逻辑检查将会在AppDomaincontext 第一次被使用的时候执行。

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

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();
}
}
}

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

Entity Framework Code First (八)迁移 Migrations的更多相关文章

  1. Entity Framework Code First 数据迁移

    需要在[工具 --> NuGet 程序包管理器 --> 程序包管理器控制台]中输入三个命令: Enable-Migrations (初次迁移时使用) Add-Migration [为本次迁 ...

  2. Asp.net Mvc Entity Framework Code First 数据库迁移

    1.创建Mvc项目 2.安装Entity Framework 2.1.如下图打开程序包管理器控制台: 2.2.输入命令Install-Package EntityFramework,即可安装Entit ...

  3. Entity Framework Code First学习系列目录

    Entity Framework Code First学习系列说明:开发环境为Visual Studio 2010 + Entity Framework 5.0+MS SQL Server 2012, ...

  4. Entity Framework Code First学习系列

    Entity Framework Code First学习系列目录 Entity Framework Code First学习系列说明:开发环境为Visual Studio 2010 + Entity ...

  5. Entity Framework Code First 迁移

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

  6. Entity Framework Code first(转载)

    一.Entity Framework Code first(代码优先)使用过程 1.1Entity Framework 代码优先简介 不得不提Entity Framework Code First这个 ...

  7. SQLITE WITH ENTITY FRAMEWORK CODE FIRST AND MIGRATION

    Last month I’ve a chance to develop an app using Sqlite and Entity Framework Code First. Before I st ...

  8. ASP.NET CORE系列【六】Entity Framework Core 之数据迁移

    原文:ASP.NET CORE系列[六]Entity Framework Core 之数据迁移 前言 最近打算用.NET Core写一份简单的后台系统,来练练手 然后又用到了Entity Framew ...

  9. Entity Framework Code First数据库连接

    1. 安装Entity Framework 使用NuGet安装Entity Framework程序包:工具->库程序包管理器->程序包管理器控制台,执行以下语句: PM> Insta ...

  10. Entity Framework Code First属性映射约定

    Entity Framework Code First与数据表之间的映射方式有两种实现:Data Annotation和Fluent API.本文中采用创建Product类为例来说明tity Fram ...

随机推荐

  1. switch结构的用法

    已知学生的名字和百分制分数.要求根据学生的百分制分数,分别采用"满分","优秀","良好","及格"和"不及格 ...

  2. 第5章 绘图基础_5.1-5.4 GDI绘图

    5.1 GDI的原理和结构 (1)提供一种特殊机制彻底隔离应用程序与不同输出设备(eg.显示器或打印机),以便支持 与设备无关的图形. 光栅设备(如显示器.激光打印机):图像是由点构成的矩阵 图形输出 ...

  3. ArrayList如何保证线程安全

    ArrayList是线程不安全的,轻量级的.如何使ArrayList线程安全? 1.继承Arraylist,然后重写或按需求编写自己的方法,这些方法要写成synchronized,在这些synchro ...

  4. 开发Adobe AIR移动应用程序的考虑事项

    http://www.adobe.com/cn/devnet/air/articles/considerations-air-apps-mobile.html Adobe AIR 经过发展演进,已经超 ...

  5. [No000039]操作系统Operating Systems用户级线程User Threads

    多进程是操作系统的基本图像 是否可以资源不动而切换指令序列? 进程 = 资源 + 指令执行序列 线程: 保留了并发的优点,避免了进程切换代价 实质就是映射表不变而PC 指针变 多个执行序列+ 一个地址 ...

  6. django复习笔记3:实战

    1.初始化 2.配置后台,增加测试数据 3.测试urls/views/templates 4.增加静态资源 5.修改样式 6.模版继承 7.增加博文主页 8.增加表单 9.完善新增页面和编辑页面的表单 ...

  7. WEBAPI 怎么保证安全

    先记录下   客户端登陆,服务端验证然后生成session,客户端每次调用接口的时候都把session带过去.服务端路由请求的时候都去验证session. 另外一种app的做法是,参数+用户名密码做s ...

  8. 【MVC】自定义Scaffold Template

    MVC提供了基本的CRUD Scaffold Template模板,创建视图的时候,只要勾选创建一个强类型视图 , 并选择模型类,就可以选择支架模板了,这些模板包括List,Detail,Create ...

  9. Codevs 1506 传话(floyd大法好)。

    1506 传话  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 白银 Silver 题解       题目描述 Description 一个朋友网络,如果a认识b,那么如果a第 ...

  10. c语言 指针与地址的区别

    指针由两部分组成,指针的类型和指针的值(也就是变量的地址). 指针和地址的区别: 地址只是一堆十六进制的字符,对应着内存条的某段内存, 而指针本身有地址,指针的值也是一个地址,指针本身还有类型,这与单 ...