EF 4.3 Code-Based Migrations Walkthrough

本文介绍了如何使用 Entity Framework 的 CodeFirst 迁移来更新数据库模式,并通过实例演示了迁移的创建、定制及数据迁移的过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Building an Initial Model & Database

Before we start using migrations we need a project and a Code First model to work with. For this walkthrough we are going to use the canonical Blog and Post model.

  1. Create a new MigrationsCodeDemo Console application.      
    .
  2. Add the latest version of the EntityFramework NuGet package to the project.      
    • Tools –> Library Package Manager –> Package Manager Console.
    • Run the ‘Install-Package EntityFramework’ command.          
      .
  3. Add a Model.cs file with the code shown below. This code defines a single Blog class that makes up our domain model and a BlogContext class that is our EF Code First context.      
    using System.Data.Entity;
    using System.Collections.Generic;
    using System.ComponentModel.DataAnnotations;
    using System.Data.Entity.Infrastructure;
    
    namespace MigrationsCodeDemo
    {
        public class BlogContext : DbContext
        {
            public DbSet<Blog> Blogs { get; set; }
        }
    
        public class Blog
        {
            public int BlogId { get; set; }
            public string Name { get; set; }
        }
    }
  4. Now that we have a model it’s time to use it to perform data access. Update the Program.cs file with the code shown below.      

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace MigrationsCodeDemo
    {
        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);
                    }
                }
            }
        }
    }
  5. Run your application and you will see that a MigrationsCodeDemo.BlogContext database is created on your local SQLEXPRESS instance.      

    MigrationsCodeDemoDatabase

 

Enabling Migrations

It’s time to make some more changes to our model.

  1. Let’s introduce a Url property to the Blog class.    
    public class Blog
    {
        public int BlogId { get; set; }
        public string Name { get; set; }
        public string Url { get; set; }
    }
    
  2. If you were to run the application again you would get an InvalidOperationException because the database no longer matches your model.    

    ”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. As the exception suggests, it’s time to start using Code First Migrations. The first step is to enable migrations for our context.    
    • Run the ‘Enable-Migrations’ command in Package Manager Console.        
      . .
  4. This command has added a Migrations folder to our project. This new folder contains two files:    
    • The Configuration class. This class allows you to configure how Migrations behaves for your context. For this walkthrough we will just use the default configuration.        
      Because there is just a single Code First context in your project, Enable-Migrations has automatically filled in the context type that this configuration applies to.
    • An InitialCreate migration. This migration was generated because we already had Code First create a database for us, before we enabled migrations. The code in this scaffolded migration represents the objects that have already been created in the database. In our case that is the Blog table with a BlogId and Name columns.

Your First Migration

Code First Migrations has two commands that you are going to become familiar with.

  • Add-Migration will scaffold the next migration based on changes you have made to your model.
  • Update-Database will apply any pending changes to the database.
  1. We need to scaffold a migration to take care of the new Url property we have added. The Add-Migration command allows us to give these migrations a name, let’s just call ours AddBlogUrl.    
    • Run the ‘Add-Migration AddBlogUrl’ command in Package Manager Console.        
      .
  2. In the Migrations folder we now have a new AddBlogUrl migration. The migration filename is pre-fixed with a timestamp to help with ordering.    
    namespace MigrationsCodeDemo.Migrations
    {
        using System.Data.Entity.Migrations;
        
        public partial class AddBlogUrl : DbMigration
        {
            public override void Up()
            {
                AddColumn("Blogs", "Url", c => c.String());
            }
            
            public override void Down()
            {
                DropColumn("Blogs", "Url");
            }
        }
    }
  3. We could now edit or add to this migration but everything looks pretty good. Let’s use Update-Database to apply this migration to the database.    
    • Run the ‘Update-Database’ command in Package Manager Console.        
      .
  4. Code First Migrations has now updated the MigrationsCodeDemo.BlogContext database to include the Url column in the Blogs table. 

    MigrationsCodeDemoDatabaseUpdated

Customizing Migrations

So far we’ve generated and run a migration without making any changes. Now let’s look at editing the code that gets generated by default.

  1. It’s time to make some more changes to our model, let’s introduce a Blog.Rating property and a new Post class.    
    public class Blog
    {
        public int BlogId { get; set; }
        public string Name { get; set; }     
        public string 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. Let’s use the Add-Migration command to let Code First Migrations scaffold its best guess at the migration for us. We’re going to call this migration AddPostClass.    
    • Run the ‘Add-Migration AddPostClass’ command in Package Manager Console.        
      .
  3. Code First Migrations did a pretty good job of scaffolding these changes, but there are some things we might want to change:    
    • First up, let’s add a unique index to Posts.Title column.
    • We’re also adding a non-nullable Blogs.Rating column, if there is any existing data in the table it will get assigned the CLR default of the data type for new column (Rating is integer, so that would be 0). But we want to specify a default value of 3 so that existing rows in the Blogs table will start with a decent rating.        

      (These changes to the scaffolded migration are highlighted)        

      namespace MigrationsCodeDemo.Migrations
      
      {
          using System.Data.Entity.Migrations;
      
          public partial class AddPostClass : DbMigration
          {
              public override void 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));
              }
      
              public override void Down()
              {
                  DropIndex("Posts", new[] { "BlogId" });
                  DropForeignKey("Posts", "BlogId", "Blogs");
                  DropColumn("Blogs", "Rating");
                  DropTable("Posts");
              }
          }
      }
  4. Our edited migration is looking pretty good, so let’s use Update-Database to bring the database up-to-date. This time let’s specify the –Verbose flag so that you can see the SQL that Code First Migrations is running.    
    • Run the ‘Update-Database –Verbose’ command in Package Manager Console.

    Data Motion / Custom SQL

    So far we have looked at migration operations that don’t change or move any data, now let’s look at something that needs to move some data around. There is no native support for data motion yet, but we can run some arbitrary SQL commands at any point in our script.

    1. Let’s add a Post.Abstract property to our model. Later, we’re going to pre-populate the Abstract for existing posts using some text from the start of the Content column.    
      public class Post
      {
          public int PostId { get; set; }
          [MaxLength(200)]
          public string Title { get; set; }
          public string Content { get; set; }
          public string Abstract { get; set; }     
      
          public int BlogId { get; set; }
          public Blog Blog { get; set; }
      }
    2. Let’s use the Add-Migration command to let Code First Migrations scaffold its best guess at the migration for us. We’re going to call this migration AddPostAbstract.    
      • Run the ‘Add-Migration AddPostAbstract’ command in Package Manager Console.        
        .
    3. The generated migration takes care of the schema changes but we also want to pre-populate the Abstract column using the first 100 characters of content for each post. We can do this by dropping down to SQL and running an UPDATE statement after the column is added.    
      namespace MigrationsCodeDemo.Migrations
      {
          using System.Data.Entity.Migrations;
          
          public partial class AddPostAbstract : DbMigration
          {
              public override void Up()
              {
                  AddColumn("Posts", "Abstract", c => c.String());
      
                  Sql("UPDATE Posts SET Abstract = LEFT(Content, 100) WHERE Abstract IS NULL");
              }
              
              public override void Down()
              {
                  DropColumn("Posts", "Abstract");
              }
          }
      }
    4. Our edited migration looks good, so let’s use Update-Database to bring the database up-to-date. We’ll specify the –Verbose flag so that we can see the SQL being run against the database.

      • Run the ‘Update-Database –Verbose’ command in Package Manager Console.

    Migrate to a Specific Version (Including Downgrade)

    So far we have always upgraded to the latest migration, but there may be times when you want upgrade/downgrade to a specific migration.

    1. Let’s say we want to migrate our database to the state it was in after running our AddBlogUrl migration. We can use the –TargetMigration switch to downgrade to this migration.    
      • Run the ‘Update-Database –TargetMigration:"AddBlogUrl"’ command in Package Manager Console.

    This command will run the Down script for our AddBlogAbstract and AddPostClass migrations.

    If you want to roll all the way back to an empty database then you can use the Update-Database –TargetMigration:$InitialDatabase command.

    Getting a SQL Script

    If another developer wants these changes on their machine they can just sync once we check our changes into source control. Once they have our new migrations they can just run the Update-Database command to have the changes applied locally. However if we want to push these changes out to a test server, and eventually production, we probably want a SQL script we can hand off to our DBA.

    1. Let’s run the Update-Database command but this time we’ll specify the –Script flag so that changes are written to a script rather than applied. We’ll also specify a source and target migration to generate the script for. We want a script to go from an empty database ($InitialDatabase) to the latest version (migration “AddPostAbstract”).    

      Note: If you don’t specify a target migration, Migrations will use the latest migration as the target.

      • Run the ‘Update-Database -Script -SourceMigration:$InitialDatabase -TargetMigration:"AddPostAbstract"’ command in Package Manager Console.        
        .
    2. Code First Migrations will run the migration pipeline but instead of actually applying the changes it will write them out to a .sql file for you. Once the script is generated, it is opened for you in Visual Studio, ready for you to view or save.

    Summary

    In this walkthrough you saw how to scaffold, edit and run code-based migrations to upgrade and downgrade your database. You also saw how to get a SQL script to apply migrations to a database.

    内容概要:该论文研究增程式电动汽车(REEV)的能量管理策略,针对现有优化策略实时性差的问题,提出基于工况识别的自适应等效燃油消耗最小策略(A-ECMS)。首先建立整车Simulink模型和基于规则的策略;然后研究动态规划(DP)算法和等效燃油最小策略;接着通过聚类分析将道路工况分为四类,并设计工况识别算法;最后开发基于工况识别的A-ECMS,通过高德地图预判工况类型并自适应调整SOC分配。仿真显示该策略比规则策略节油8%,比简单SOC规划策略节油2%,并通过硬件在环实验验证了实时可行性。 适合人群:具备一定编程基础,特别是对电动汽车能量管理策略有兴趣的研发人员和技术爱好者。 使用场景及目标:①理解增程式电动汽车能量管理策略的基本原理;②掌握动态规划算法和等效燃油消耗最小策略的应用;③学习工况识别算法的设计和实现;④了解基于工况识别的A-ECMS策略的具体实现及其优化效果。 其他说明:此资源不仅提供了详细的MATLAB/Simulink代码实现,还深入分析了各算法的原理和应用场景,适合用于学术研究和工业实践。在学习过程中,建议结合代码调试和实际数据进行实践,以便更好地理解策略的优化效果。此外,论文还探讨了未来的研究方向,如深度学习替代聚类、多目标优化以及V2X集成等,为后续研究提供了思路。
    评论
    添加红包

    请填写红包祝福语或标题

    红包个数最小为10个

    红包金额最低5元

    当前余额3.43前往充值 >
    需支付:10.00
    成就一亿技术人!
    领取后你会自动成为博主和红包主的粉丝 规则
    hope_wisdom
    发出的红包
    实付
    使用余额支付
    点击重新获取
    扫码支付
    钱包余额 0

    抵扣说明:

    1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
    2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

    余额充值