Entity Framework first code

  1. EF43 基于代码的迁移演练
  2. 准备工作
  3. 创建初始的模型和数据库
  4. 启用迁移
  5. 第一个迁移
  6. 定制迁移
  7. 数据操作定制 SQL
  8. 迁移到特定版本包含降级
  9. 获取迁移的脚本
 
 

EF4.3 基于代码的迁移演练

原文地址:http://blogs.msdn.com/b/adonet/archive/2012/02/09/ef-4-3-code-based-migrations-walkthrough.aspx

原文名称:EF 4.3 Code-Based Migrations Walkthrough

准备工作

在开始之前,我们需要一个项目,以及一个 Code First 的模型,对于这次演示,我们使用典型的博客 Blog 和回复 Post 模型。

1. 创建新的  MigrationsCodeDemo 控制台应用程序

2. 为项目添加最新版本的 EntityFramework NuGet 包。

找到包管理器控制台。

运行 Install-Package EntityFramework 命令。

成功之后的项目文件如下:

创建初始的模型和数据库

1. 增加如下的 Model.cs 文件,代码定义了一个单个的 Blog 类表示我们的模型对象,BlogContext 类就是 EF Code First 的上下文。

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

namespace MigrationsCodeDemo
{
    publicclass BlogContext : DbContext
    {
        public DbSet<Blog> Blogs { get; set; }
    }

    publicclass Blog
    {
        publicint BlogId { get; set; }
        publicstring Name { get; set; }
    }
}
 

2. 现在我们已经有了一个模型,是时候进行一次数据访问了。使用如下的代码更新 Program.cs 文件。

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

namespace MigrationsCodeDemo
{
    class Program
    {
        staticvoid 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);
                }
            }
        }
    }
}
3. 运行程序,现在就可以在你本地的 SQLExpress 数据库中看到数据库了。

启用迁移

1. 在 Blog 类中增加一个 Url 属性。

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

2. 现在运行程序,会看到如下的异常。
未经处理的异常:  System.InvalidOperationException: 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).

3. 正如异常建议,现在是开始使用 Code First 迁移的时候了,第一步是为我们的上下文启用迁移支持。

   在包管理器的控制台中执行命令:Enable-Migrations

4. 这个命令在项目中增加名为 Migrations 文件夹,文件夹中包含两个文件。

Configuration 类,这个类允许你配置你的上下文的迁移行为,在这个演示中,我们仅仅使用默认配置。

因为在这个项目中只有一个上下文,Enable-Migrations 自动填充应用的这个上下文。

201202171353373_InitialCreate.cs 中的 InitialCreate ,生成这个迁移是因为我们已经通过 Code First 创建了一个数据库。这个迁移中的代码表示我们已经创建的数据库,

 

namespace
MigrationsCodeDemo.Migrations
{
    using System.Data.Entity.Migrations;
    
    publicpartialclass InitialCreate : DbMigration
    {
        publicoverridevoid Up()
        {
            CreateTable(
                "Blogs",
                c => new
                    {
                        BlogId = c.Int(nullable: false, identity: true),
                        Name = c.String(),
                    })
                .PrimaryKey(t => t.BlogId);
            
        }
        
        publicoverridevoid Down()
        {
            DropTable("Blogs");
        }
    }
}
 

第一个迁移

你会使用到两个命令

Add-Migration,将会基于你对模型的修改创建一个迁移的脚手架。

Update-Database,将没有提交的修改提交到数据库。

1. 我们首先为我们新增加的 Url 属性创建一个迁移,Add-Migration 会帮我们完成这个工作,我们为这个迁移命名为:AddBlogUrl。

 执行:Add-Migration AddBlogUrl

项目中增加了一个文件 201202171413369_AddBlogUrl.cs

 

 

内容如下:

 

namespace
MigrationsCodeDemo.Migrations
{
    using System.Data.Entity.Migrations;
    
    publicpartialclass AddBlogUrl : DbMigration
    {
        publicoverridevoid Up()
        {
            AddColumn("Blogs", "Url", c => c.String());
        }
        
        publicoverridevoid Down()
        {
            DropColumn("Blogs", "Url");
        }
    }
}
 

3. 我们可以在这个迁移中编辑或者增加内容,但是现在看起来就很不错,让我们将这个迁移提交到数据库中。

执行: Update-Database

4. 现在的数据库中已经包含了 Url 列。

定制迁移

下面我们看看如何定制迁移。

1. 在代码中增加一个回复的类 Post,同时在 Blog 中增加一个评分属性。

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

namespace MigrationsCodeDemo
{
    publicclass Blog
    {
        publicint BlogId { get; set; }
        publicstring Name { get; set; }         
        publicstring Url { get; set; }
        public int Rating { get; set; }        public List<Post> Posts { get; set; }
    }

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

2. 使用 Add-Migration 命令创建一个迁移,命名为 AddPostClass。

3.  Code First Migrations 帮我们创建好了一个迁移,但是我们希望能增加如下的修改:

     首先,为 Posts.Title 增加一个唯一索引。

     增加一个非空的 Blogs.Rating 列,如果表中已经存在了数据,那么就将 CLR 默认的数据类型值赋予新增加的列 (Rating 是整数类型,应该就是 0), 但是,我们希望默认为 3, 这样已经存在的博客会有一个不错的评分。

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

    publicpartialclass AddPostClass : DbMigration
    {
        publicoverridevoid Up()
        {
            CreateTable(
                "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("Blogs", t => t.BlogId, cascadeDelete: true)
                .Index(t => t.BlogId)
                .Index(p => p.Title, unique: true);

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

        publicoverridevoid Down()
        {
            DropIndex("Posts", new[] { "BlogId" });
            DropForeignKey("Posts", "BlogId", "Blogs");
            DropColumn("Blogs", "Rating");
            DropTable("Posts");
        }
    }
}
 

4. 运行 Update-Database 提交到数据库,这次可以使用一个参数 -Verbose,以便可以看到生成的 SQL 脚本。

数据操作/定制 SQL

我们已经完成的迁移并没有修改或者移动任何数据,我们可以在迁移中的任何地点运行任意脚本。

1. 在模型上增加一个摘要 PostAbstrack 属性,然后,希望使用已经发布的内容来填充这个摘要属性。

public
class
Post
{
    publicint PostId { get; set; }
    [MaxLength(200)]
    publicstring Title { get; set; }
    publicstring Content { get; set; }
    public string Abstract { get; set; }publicint BlogId { get; set; }
    public Blog Blog { get; set; }
}
 

2. 创建一个迁移。

3. 修改生成的迁移文件,

namespace
MigrationsCodeDemo.Migrations
{
    using System.Data.Entity.Migrations;
    
    publicpartialclass AddPostAbstract : DbMigration
    {
        publicoverridevoid Up()
        {
            AddColumn("Posts", "Abstract", c => c.String());

            Sql("UPDATE Posts SET Abstract = LEFT(Content, 100) WHERE Abstract IS NULL");

        }
        
        publicoverridevoid Down()
        {
            DropColumn("Posts", "Abstract");
        }
    }
}
 

4. 更新数据库之后,就会得到最新的数据了。使用 Verbose 参数可以看到提交的脚本。


迁移到特定版本(包含降级)

你可以升级或者降级到特定的版本。

假设我们希望数据库迁移到执行 AddBlogUrl 迁移之后的状态,通过 -TargetMigration 参数来降级。

如果你希望回到最初的空数据库,可以使用参数 TargetMigration:$InitialDatabase.

获取迁移的脚本

在运行 Update-Database 的时候,使用参数 -Script 。

-SourceMigration:$InitialDatabase 用来指定起始的版本, -TargetMigration:"AddPostAbstract" 用来指定目标版本。

我们希望取得从初始的数据库,直到迁移到 AddPostAbstract 版本使用的脚本。

执行之后,得到一个脚本文件。

CREATE
TABLE
[ Blogs ]
(
    [BlogId][int]NOTNULLIDENTITY,
    [Name][nvarchar](max),
    CONSTRAINT[PK_Blogs]PRIMARYKEY ([BlogId])
)
CREATETABLE[__MigrationHistory] (
    [MigrationId][nvarchar](255) NOTNULL,
    [CreatedOn][datetime]NOTNULL,
    [Model][varbinary](max) NOTNULL,
    [ProductVersion][nvarchar](32) NOTNULL,
    CONSTRAINT[PK___MigrationHistory]PRIMARYKEY ([MigrationId])
)
BEGIN TRY
    EXEC sp_MS_marksystemobject '__MigrationHistory'END TRY
BEGIN CATCH
END CATCH
INSERTINTO[__MigrationHistory] ([MigrationId], [CreatedOn], [Model], [ProductVersion]) VALUES ('201202171353373_InitialCreate', '2012-02-17T14:51:25.032Z', 0x1F8B0800000000000400ECBD07601C499625262F6DCA7B7F4AF54AD7E074A10880601324D8904010ECC188CDE692EC1D69472329AB2A81CA6556655D661640CCED9DBCF7DE7BEFBDF7DE7BEFBDF7BA3B9D4E27F7DFFF3F5C6664016CF6CE4ADAC99E2180AAC81F3F7E7C1F3F22FEC7BFF71F7CFC7BBC5B94E9655E3745B5FCECA3DDF1CE4769BE9C56B36279F1D947EBF67CFBE0A3DFE3E8374E1E9FCE16EFD29F34EDF6D08EDE5C369F7D346FDBD5A3BB779BE93C5F64CD78514CEBAAA9CEDBF1B45ADCCD66D5DDBD9D9D83BBBB3B777302F111C14AD3C7AFD6CBB658E4FC07FD79522DA7F9AA5D67E517D52C2F1BFD9CBE79CD50D317D9226F56D934FFECA32F8A8B3A6B098BE684DA3ECD17D547E971596484C9EBBC3C7F4FB4761E02AD8F6C87D4E529A1D65EBFB95EE5DCED671F3D29AB0BBF05B5F9BDF2EBE003FAE8655DADF2BABD7E959F7BEF9DCD3E4AEF86EFDEEDBE6C5FEDBC07143EFBE86CD9DEDBFB287DB12ECB6C52D207E759D9E41FA5AB4F1FBD6EAB3AFF3C5FE644907CF6326BDBBCA6C9399BE53C0425C5A3D5A7B7A3C6C3BB3B7BA0C6DD6CB9AC5AA6710FF90EAAF8D720FABAAD89693E4A9F15EFF2D9F37C79D1CE2DB25F64EFCC27F4EB47E957CB82788C5E6AEB75EE0F4EFEDEDCE95775F9B3DCE7E3BB8E09FAAC41DCDA660551DD9B2F7C96BF6B3B6C22ED5FE7ADD7B2F92875C08567C7CC61510C6C5F4E24EE8A4C18D9B93B203C8FBFC8562B228E274CFA49FA5A24E964FBF5FB4BCB4260DC9D3611A1B1D8DA9E8843B38BBCF32D754D983E2BEAA67D9AB5D924C3749DCC16BD66B7A0ACE9C9277057341DBD4D6BFC2E6FF4D5C9B82FEF0C45DF7D46035A9080F1D8746484474C4DE88BAFA75999D503427E5295EBC57293C2D80445E4CF87219FDC1E020B930F803FE8BFFFF86E67FC5D227B22A32D3B6AAF3B659BB8BDDBC4F66EB9BEC3DD8F95D36EB61F3DD693261FA54498CB6206B67B7DDDB4F9628C06E3D7BFA83C290B1AAF6BF045B62CCEF3A67D53BDCD610B4932BEBE09B24AB76966E5FF9BED500112DC68717A66EAF6F6637999D5D379566F2DB277773EC026BC079CF7D3F37DA575B3B61F54F6C2759F7D349B90FFF2461054F3F035ED405F021EDFF5FDACC74FF3A6B87020E0752DF329749F036ADA9C2DCF2B43621A918F9169D299812FF2369B11618EEBB638CFA62D7D3DCD9B86CDF34F66E59A9A9C2E26F9EC6CF9E5BA5DADDBE3A6C91793F2DA1FEFE3BB9BFB676317E2FCF8CB156BEF6F620884664143C8BF5C3E5917E5CCE2FDACCFCA4320C0232A1F8415B92704EEE2DA427A512D6F0948C9F7345FE54B48D79B7CB12A0958F3E5F27576990FE376330D438A3D7E5A646402173E05E513C5E475463D7B5D5007FE1BAE3FFA93D8959CFCA3FF270000FFFF2B65B379590C0000, '4.3.0')
ALTERTABLE[Blogs]ADD[Url][nvarchar](max)
INSERTINTO[__MigrationHistory] ([MigrationId], [CreatedOn], [Model], [ProductVersion]) VALUES ('201202171413369_AddBlogUrl', '2012-02-17T14:51:25.079Z', 0x1F8B0800000000000400ECBD07601C499625262F6DCA7B7F4AF54AD7E074A10880601324D8904010ECC188CDE692EC1D69472329AB2A81CA6556655D661640CCED9DBCF7DE7BEFBDF7DE7BEFBDF7BA3B9D4E27F7DFFF3F5C6664016CF6CE4ADAC99E2180AAC81F3F7E7C1F3F22FEC7BFF71F7CFC7BBC5B94E9655E3745B5FCECA3DDF1CE4769BE9C56B36279F1D947EBF67CFBE0A3DFE3E8374E1E9FCE16EFD29F34EDF6D08EDE5C369F7D346FDBD5A3BB779BE93C5F64CD78514CEBAAA9CEDBF1B45ADCCD66D5DDBD9D9D83BBBB3B777302F111C14AD3C7AFD6CBB658E4FC07FD79522DA7F9AA5D67E517D52C2F1BFD9CBE79CD50D317D9226F56D934FFECA32F8A8B3A6B098BE684DA3ECD17D547E971596484C9EBBC3C7F4FB4761E02AD8F6C87D4E529A1D65EBFB95EE5DCED671F3D29AB0BBF05B5F9BDF2EBE003FAE8655DADF2BABD7E959F7BEF9DCD3E4AEF86EFDEEDBE6C5FEDBC07143EFBE86CD9DEDBFB287DB12ECB6C52D207E759D9E41FA5AB4F1FBD6EAB3AFF3C5FE644907CF6326BDBBCA6C9399BE53C0425C5A3D5A7B7A3C6C3BB3B7BA0C6DD6CB9AC5AA6710FF90EAAF8D720FABAAD89693E4A9F15EFF2D9F37C79D1CE2DB25F64EFCC27F4EB47E957CB82788C5E6AEB75EE0F4EFEDEDCE95775F9B3DCE7E3BB8E09FAAC41DCDA660551DD9B2F7C96BF6B3B6C22ED5FE7ADD7B2F92875C08567C7CC61510C6C5F4E24EE8A4C18D9B93B203C8FBFC8562B228E274CFA49FA5A24E964FBF5FB4BCB4260DC9D3611A1B1D8DA9E8843B38BBCF32D754D983E2BEAA67D9AB5D924C3749DCC16BD66B7A0ACE9C9277057341DBD4D6BFC2E6FF4D5C9B82FEF0C45DF7D46035A9080F1D8746484474C4DE88BAFA75999D503427E5295EBC57293C2D80445E4CF87219FDC1E020B930F803FE8BFFFF86E67FC5D227B22A32D3B6AAF3B659BB8BDDBC4F66EB9BEC3DD8F95D36EB61F3DD693261FA54498CB6206B67B7DDDB4F9628C06E3D7BFA83C290B1AAF6BF045B62CCEF3A67D53BDCD610B4932BEBE09B24AB76966E5FF9BED500112DC68717A66EAF6F6637999D5D379566F2DB277773EC026BC079CF7D3F37DA575B3B61F54F6C2759F7D349B90FFF2461054F3F035ED405F021EDFF5FDACC74FF3A6B87020E0752DF329749F036ADA9C2DCF2B43621A918F9169D299812FF2369B11618EEBB638CFA62D7D3DCD9B86CDF34F66E59A9A9C2E26F9EC6CF9E5BA5DADDBE3A6C91793F2DA1FEFE3BB9BFB676317E2FCF8CB156BEF6F620884664143C8BF5C3E5917E5CCE2FDACCFCA4320C0232A1F8415B92704EEE2DA427A512D6F0948C9F7345FE54B48D79B7CB12A0958F3E5F27576990FE376330D438A3D7E5A646402173E05E513C5E475463D7B5D5007FE1BAE3FFA93D8959CFCA3FF270000FFFF2B65B379590C0000, '4.3.0')
CREATETABLE[Posts] (
    [PostId][int]NOTNULLIDENTITY,
    [Title][nvarchar](200),
    [Content][nvarchar](max),
    [BlogId][int]NOTNULL,
    CONSTRAINT[PK_Posts]PRIMARYKEY ([PostId])
)
CREATEINDEX[IX_BlogId]ON[Posts]([BlogId])
CREATEUNIQUEINDEX[IX_Title]ON[Posts]([Title])
ALTERTABLE[Blogs]ADD[Rating][int]NOTNULLDEFAULT3ALTERTABLE[Posts]ADDCONSTRAINT[FK_Posts_Blogs_BlogId]FOREIGNKEY ([BlogId]) REFERENCES[Blogs] ([BlogId]) ONDELETECASCADEINSERTINTO[__MigrationHistory] ([MigrationId], [CreatedOn], [Model], [ProductVersion]) VALUES ('201202171424494_AddPostClass', '2012-02-17T14:51:25.092Z', 0x1F8B0800000000000400ECBD07601C499625262F6DCA7B7F4AF54AD7E074A10880601324D8904010ECC188CDE692EC1D69472329AB2A81CA6556655D661640CCED9DBCF7DE7BEFBDF7DE7BEFBDF7BA3B9D4E27F7DFFF3F5C6664016CF6CE4ADAC99E2180AAC81F3F7E7C1F3F22FEC7BFF71F7CFC7BBC5B94E9655E3745B5FCECA3DDF1CE4769BE9C56B36279F1D947EBF67CFBE0A3DFE3E8374E1E9FCE16EFD29F34EDF6D08EDE5C369F7D346FDBD5A3BB779BE93C5F64CD78514CEBAAA9CEDBF1B45ADCCD66D5DDBD9D9D83BBBB3B777302F111C14AD3C7AFD6CBB658E4FC07FD79522DA7F9AA5D67E517D52C2F1BFD9CBE79CD50D317D9226F56D934FFECA32F8A8B3A6B098BE684DA3ECD17D547E971596484C9EBBC3C7F4FB4761E02AD8F6C87D4E529A1D65EBFB95EE5DCED671F3D29AB0BBF05B5F9BDF2EBE003FAE8655DADF2BABD7E959F7BEF9DCD3E4AEF86EFDEEDBE6C5FEDBC07143EFBE86CD9DEDBFB287DB12ECB6C52D207E759D9E41FA5AB4F1FBD6EAB3AFF3C5FE644907CF6326BDBBCA6C9399BE53C0425C5A3D5A7B7A3C6C3BB3B7BA0C6DD6CB9AC5AA6710FF90EAAF8D720FABAAD89693E4A9F15EFF2D9F37C79D1CE2DB25F64EFCC27F4EB47E957CB82788C5E6AEB75EE0F4EFEDEDCE95775F943EFF31591031D6D9E930E8C17D96571C174EC407B59356DF351FA2A2F8593E7C54AB8778C6F7E7F66B8F4595D2D5E55A536E70F7FFF37597D91B78446D5FDE675B5AEA71D141EDF75BCBC91C301E6EB7038DEFB3A1C6EDEFBFF0087BF29DAF27D599C7AFA40762385D8D210DFB3DF0F67F3DBA99EDBB2B9F0F1FB73B9E1E53E971BFEBF0D971F374D352DB86B8FEDA4DB7000A7CB593A88834C80C19AE8BD2EDB62551653EAF2B38FBED5A3460C98155B074C461F02DB0DF122605F2E9FE665DEE6E9F114E320C6C89A6936EBCF01D160167E42529AD71093AC246E6ADA3A2B966D5FA48BE5B45865E510CA9D17DEC3CE01290BBEFBCDD37C952F21C44374FFB07E2DF80E916EA2C9E3BB1ED3F43526A492DEC86B0F0196D4775DED29ED5FE7ADD79214BE63D4800B7A1C14BEACD6A2F7B2F063E7656F0021049537EFFB9E3076E9B8492E2C9216BFDE346C9204EF75A54D97A1C38144E4DDCE86FDEEF15D7117F583C77707FCCAC75F64AB152954CFCFD44FD2D7E2649E6CBF7E7F47722130EE4E9B883F69B1B53D9169CB2EF2CEB750FDB3FC595137EDD3ACCD2619F4EDC96CD16B760BDE333DF92CD89F23C354A6357E9737FA9EF63

猜你喜欢

转载自chuchanggeng-15.iteye.com/blog/2334313