精進不休 .NET 4.0 (10) - ADO.NET Entity Framework 4.3 之 Code First 下自動更新數據庫結構(Automatic Migrations)
作者:webabcd
介紹
ADO.NET Entity Framework 4.3 的新特性:Code First 下自動更新數據庫結構(Automatic Migrations)
示例
Web.config
<?xml version="1.0" encoding="utf-8"?> <configuration> <configSections> <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=4.3.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" /> </configSections> <system.web> <compilation debug="true" targetFramework="4.0" /> </system.web> <connectionStrings> <!-- 需要將 Persist Security Info 設置為 True,以便保存密碼信息 因為 Database.SetInitializer<MyContext>(new DropCreateDatabaseIfModelChanges<MyContext>()); 在判斷 Code First 與數據庫結構是否一致時需要連接 master 庫 --> <add name="MyConnection" providerName="System.Data.SqlClient" connectionString="server=.;database=MyDB;uid=sa;pwd=111111;Persist Security Info=True" /> </connectionStrings> </configuration>
Product.cs
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.ComponentModel.DataAnnotations; namespace EF43.UpdateSchema { [Table("Product")] public class Product { [Key] [DatabaseGenerated(DatabaseGeneratedOption.Identity)] public int ProductId { get; set; } [Required] [Column("ProductName", TypeName="varchar")] public string Name { get; set; } /* 為了測試 Automatic Migrations 可放開此注釋,然后 Add-Migration 的話會自動生成結構遷移的相關代碼 public double Price { get; set; } */ } }
MyContext.cs
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Data.Entity; namespace EF43.UpdateSchema { // 創建的 Context 要繼承自 DbContext public class MyContext : DbContext { // 指定數據庫連接為:connectionStrings 中的 MyConnection public MyContext() : base("MyConnection") { } public DbSet<Product> Products { get; set; } } }
Demo.aspx.cs
/* * 通過 NuGet 下載 Entity Framework 4.3 * * 關於 Code First 下自動更新數據庫結構(Automatic Migrations)的相關說明如下: * 注:需要通過 NuGet 的 Package Manager Console 輸入相關命令 * * 在更新了實體結構后輸入如下命令 * 1、Enable-Migrations * 啟動遷移功能,會在項目根目錄下生成 Migrations 文件夾,其內通常會有兩個文件 * 1. Configuration.cs - 相關配置,如是否需要自動遷移(默認為 false)等 * 2. 201202290715581_InitialCreate.cs - 未遷移前的數據結構,前半部分為時間戳 * * 2、Add-Migration -StartupProjectName EF43 * 在指定的項目中增加一個遷移點,此命令后會要求輸入一個 Name 參數,此參數的值為遷移點名稱 * 假設輸入的遷移點名稱為 MyFirstTest 則會生成一個類似如下的文件 201202290718442_MyTestFirst.cs,其包含兩個方法 Up() 和 Down(),分別用於此遷移點的升級和降級 * * 3、Update-Database -StartupProjectName EF43(將指定的項目的數據庫結構升級到最新) * Update-Database -TargetMigration:"201202290718442_MyTestFirst",將當前數據庫結構升級到此遷移點(無參數 -TargetMigration 則為升級到最新) * Update-Database -Script,顯示用於更新數據庫結構的相關 sql 代碼 * Update-Database -Script -SourceMigration:"aaa" -TargetMigration:"bbb",顯示將遷移點“aaa”升/降級到遷移點“bbb”的相關 sql 代碼 * * 注:如果發生“System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation”異常,請查看是否顯示指定了項目名(本例為 -StartupProjectName EF43) */ using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; using System.Data.Entity; namespace EF43.UpdateSchema { public partial class Demo : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { using (var db = new MyContext()) { Random random = new Random(); var product = new Product { Name = "windows " + random.Next() }; db.Products.Add(product); int recordsAffected = db.SaveChanges(); Response.Write("影響到數據庫的行數:" + recordsAffected.ToString()); } } } }
Migrations/Configuration.cs
namespace EF43.Migrations { using System; using System.Data.Entity; using System.Data.Entity.Migrations; using System.Linq; internal sealed class Configuration : DbMigrationsConfiguration<EF43.UpdateSchema.MyContext> { public Configuration() { // 默認情況下不會自動遷移數據庫結構,還有許多其它相關設置,詳看 DbMigrationsConfiguration<TContext> AutomaticMigrationsEnabled = false; } protected override void Seed(EF43.UpdateSchema.MyContext 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" } // ); // } } }
Migrations/201202290715581_InitialCreate.cs
namespace EF43.Migrations { using System.Data.Entity.Migrations; public partial class InitialCreate : DbMigration { public override void Up() { CreateTable( "Product", c => new { ProductId = c.Int(nullable: false, identity: true), ProductName = c.String(nullable: false, unicode: false), }) .PrimaryKey(t => t.ProductId); } public override void Down() { DropTable("Product"); } } }
Migrations/201202290718442_MyTestFirst.cs
namespace EF43.Migrations { using System.Data.Entity.Migrations; public partial class MyTestFirst : DbMigration { public override void Up() { // AddColumn("Product", "Price", c => c.Double(nullable: false)); // 自動生成的代碼如上,下面是我自定義的,用於設置新增字段的默認值 // 還有許多其它相關設置,詳看 DbMigration AddColumn("Product", "Price", c => c.Double(nullable: false, defaultValue: 10d)); } public override void Down() { DropColumn("Product", "Price"); } } }
OK
[源碼下載]
