C# EF codefirst 遷移 Migrations
遷移 Migrations
建立初始模型和資料庫——使用Migrations前的準備
在開始使用遷移(Migrations)之前,我們需要一個 Project 和一個 Code First Model, 對於本文將使用典型的 Blog 和 Post 模型
- 建立一個新的控制檯應用程式 MigrationsDemo;
- 新增最新的 EntityFramework 到專案
- Tools –> Library Package Manager –> Package Manager Console
- 執行命令 Install-Package EntityFramework
- Tools –> Library Package Manager –> Package Manager Console
- 建立 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>
再次執行就行了,讓我們看一下後臺生成的資料庫
啟用遷移——使用migrations的第一步
我們對模型 Blog 做一些更改:增加一個 Url 屬性 ——使用migrations的場景
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 (列 BlogId 和 Name). 檔名包含一個 timestamp 以便排序(如果之前資料庫沒有被建立,那麼 InitialCreate migration 將不會被建立,相反,當我們第一次呼叫 Add-Migration 的時候所有表都將歸集到一個新的 migration 中)
多個實體鎖定同一資料庫
當使用 EF6 之前的版本時,只會有一個 Code First Model 被用來生成/管理資料庫的 Schema, 這將導致每個資料庫只會有一張 __MigrationsHistory 表,從而無法辨別實體與模型的對應關係。
從 EF6 開始,Configuration 類將會包含一個 ContextKey 屬性,它將作為每一個 Code First Model 的唯一識別符號, __MigrationsHistory 表中一個相應地的列允許來自多個模型(multiple models)的實體共享表(entries),預設情況下這個屬性被設定成 context 的完全限定名。
生成、執行遷移——使用migrations的第二、三步
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)——應用migrations的效果
定製化遷移——比migratins的基礎使用高階一點(三個基本步驟之外我們還可以這樣做。。。)
到目前為止我們生成並運行了一個遷移,但是沒有對遷移做任何更改,下面我們將嘗試做一些更改:在類 Bolg 上增加一屬性 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 中新增 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: 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"); } } }
接下來我們對遷移做些更改:
- 在 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: 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"); } } }
在 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 (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
產生冪等指令碼(EF6+)
從 EF6 開始,如果你使用 –SourceMigration $InitialDatabase, 產生的指令碼將是冪等的,冪等指令碼意味著無論資料庫當前處於什麼版本/狀態,都能升級至最新版本或指定版本(指定 –TargetMigration),生成的指令碼包括檢查表 __MigrationsHistory 的邏輯以及只更新之前從未更新的
在應用程式啟動時自動升級(MigrateDatabaseToLatestVersion初始化器)
當你釋出部署應用程式的時候,可能希望當程式啟動的時候它自動更新資料庫(更新應用任何未更新的遷移),你可以通過註冊 MigrateDatabaseToLatestVersion 資料庫初始化器來實現這一點,資料庫初始化器只包含一些邏輯檢查用於確保資料庫被正確設定,這個邏輯檢查將會在AppDomain 的 context 第一次被使用的時候執行。
當我們建立一個初始化器的例項時,需要指定 context type(BlogContext)以及 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://panchunting.cnblogs.com/
本文版權歸作者和部落格園共有,歡迎轉載,但未經作者同意必須保留此段宣告,且在文章頁面明顯位置給出原文連線,否則保留追究法律責任的權利.