zoukankan      html  css  js  c++  java
  • Entity Framework CodeFirst数据迁移

    前言

    紧接着前面一篇博文Entity Framework CodeFirst尝试

    我们知道无论是“Database First”还是“Model First”当模型发生改变了都可以通过Visual Studio设计视图进行更新,那么对于Code First如何更新已有的模型呢?今天我们简单介绍一下Entity Framework的数据迁移功能。

    Entity Framework配置

     当我们对项目进行Entity Framework进行安装引用的时候,同时生成了两个配置文件

    packages.config文件:

    <?xml version="1.0" encoding="utf-8"?>
    <packages>
      <package id="EntityFramework" version="5.0.0" targetFramework="net45" />
    </packages>
    

     App.config文件:

    <?xml version="1.0" encoding="utf-8"?>
    <configuration>
      <configSections>
        <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
        <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
      </configSections>
      <startup>
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
      </startup>
      <entityFramework>
        <defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
          <parameters>
            <parameter value="v11.0" />
          </parameters>
        </defaultConnectionFactory>
      </entityFramework>
    </configuration>
    

     packages.config内容比较简单,首先是EF自身版本,然后在安装过程中根据当前应用的.NET Framework版本配置了“targetFramework”,因为不同的.NET Framework版本对应的EF程序集不同,这在安装过程中会自动识别并配置。

    App.config中自动添加了“entityFramework”配置节,在EF包安装过程中自动根据当前环境配置了“defaultConnectionFactory”, “defaultConnectionFactory”是EF默认的连接配置,只有在没有配置连接字符串时生效。

     配置了数据库链接字符串的App.config配置文件

    <?xml version="1.0" encoding="utf-8"?>
    <configuration>
      <configSections>
        <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
        <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
      </configSections>
      <connectionStrings>
        <add name="CodeFirstTest" connectionString="Data Source=.;Database=CodeFirstTest;UID=sa;PWD=sa123;" providerName="System.Data.SqlClient"></add>
      </connectionStrings>
      <startup>
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
      </startup>
      <entityFramework>
        <defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
          <parameters>
            <parameter value="v11.0" />
          </parameters>
        </defaultConnectionFactory>
      </entityFramework>
    </configuration>

    CodeFirst 数据迁移

    现在让我们在上一篇文章的Entity Framework CodeFirst尝试 的基础上给Order添加一个"Employee”属性,然后运行,不出意外的话你将看到如下异常:

     从异常信息我们可以看出,EF已经检测到模型发生了改变,建议我们使用”Code First Migrations”对模型进行更新。

    在开始Code First数据库迁移之前,我们先对上一节编写的OrderTestContext类进行修改添加默认构造函数,因为Code First Migrations将会使用数据库上下文的默认构造函数进行数据迁移操作(尽管没有默认构造函数所有的数据操作都能正常进行,但是对于数据迁移这是必须的),因此我们需要添加一个默认构造函数,并且该构造函数中必须传入我们的数据库连接名称,否则将会把更新应用到EF默认数据库上。下面是我们的OrderTestContext:

        public class OrderTestContext:DbContext
        {
            public OrderTestContext():base("CodeFirstTest")
            { 
                
            }
    
            public OrderTestContext(string connectionName)
                : base(connectionName)
            {
            }
            public DbSet<Order> Orders { get;set;}
    
            public DbSet<OrderDetail> OrderDetails { get; set; }
        }
    

    下面我们将借助于”Code First Magrations” 进行模型更新。然后找到如下图所示的位置

    1.在“程序包管理器控制台”键入命令:Enable-Migrations -ProjectName  CodeFirstTest

    如果多次执行此命令可以添加-Force参数

     

    添加后,项目中添加了一个名为Migrations的文件夹

    查看Configuration文件中的代码为:

    namespace CodeFirstTest.Migrations
    {
        using System;
        using System.Data.Entity;
        using System.Data.Entity.Migrations;
        using System.Linq;
    
        internal sealed class Configuration : DbMigrationsConfiguration<CodeFirstTest.OrderTestContext>
        {
            public Configuration()
            {
                AutomaticMigrationsEnabled = false;
            }
    
            protected override void Seed(CodeFirstTest.OrderTestContext 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" }
                //    );
                //
            }
        }
    }
    

     方法Seed中可以进行数据迁移后的数据初始化工作,将在每次迁移之后运行。如上代码所示,AddOrUpdate是IDbSet<TEntity>的扩展方法,如果指定条件的数据不存在,则会添加,如果存在,会更新。所以,如果数据是通过此方法来初始化的,在与业务更新之后,再次进行数据迁移后,还是会被还原。

    还有一个名为InitialCreate的类,配置生成数据库的细节:

    namespace CodeFirstTest.Migrations
    {
        using System;
        using System.Data.Entity.Migrations;
        
        public partial class InitialCreate : DbMigration
        {
            public override void Up()
            {
                CreateTable(
                    "dbo.Orders",
                    c => new
                        {
                            ID = c.Int(nullable: false, identity: true),
                            Customer = c.String(),
                            OrderDate = c.DateTime(nullable: false),
                        })
                    .PrimaryKey(t => t.ID);
                
                CreateTable(
                    "dbo.OrderDetails",
                    c => new
                        {
                            ID = c.Int(nullable: false, identity: true),
                            Product = c.String(),
                            OrderID = c.Int(nullable: false),
                        })
                    .PrimaryKey(t => t.ID)
                    .ForeignKey("dbo.Orders", t => t.OrderID, cascadeDelete: true)
                    .Index(t => t.OrderID);
                
            }
            
            public override void Down()
            {
                DropIndex("dbo.OrderDetails", new[] { "OrderID" });
                DropForeignKey("dbo.OrderDetails", "OrderID", "dbo.Orders");
                DropTable("dbo.OrderDetails");
                DropTable("dbo.Orders");
            }
        }
    }
    

    3.执行“Add-Migration AddEmployee”命令,添加一个名为AddEmployee的迁移

     

    4.执行“Update-Database”命令,更新数据库架构

    如果更新数据库存在冲突而不能执行更新,可以添加 -Force强制执行,例如:“Update-Database -Force”

    5.设置自动迁移

    每次都通过控制台来进行迁移太过麻烦,可以设置为自动迁移。

      1. AutomaticMigrationsEnabled:获取或设置 指示迁移数据库时是否可使用自动迁移的值。

      2. AutomaticMigrationDataLossAllowed:获取或设置 指示是否可接受自动迁移期间的数据丢失的值。如果设置为false,则将在数据丢失可能作为自动迁移一部分出现时引发异常。

        3.在Global.asax.cs中添加初始化策略

    Database.SetInitializer(new MigrateDatabaseToLatestVersion<OrderTestContext, Configuration>());

    代码调用实例

                using (var db = new OrderTestContext("CodeFirstTest"))
                {
                    Order Order = new Order();
                    Order.Customer = "aehyok";
                    Order.OrderDate = DateTime.Now;
                    db.Orders.Add(Order);
                    db.SaveChanges();
    
                    IQueryable<Order> Orders = from Orderes in db.Orders
                                               select Orderes;
                    foreach (Order O in Orders)
                    {
                        Console.WriteLine("OrderID is {0},Customer is {1}", O.ID, O.Customer);
                    }
                }
    

     调用结果展示

    有两条数据,一条是上一篇博文添加的数据,第二条就是今天测试添加的。

  • 相关阅读:
    初听余杭...
    生命里走了一位花儿,同时却遇到了10年未见的老同学
    两个馒头过中秋
    周末粉红色的回忆
    jQuery图片剪裁插件 Jcrop
    上周六出去烤肉随便拍了几张
    一周学会Mootools 1.4中文教程:(7)汇总收尾
    30天学会 MooTools 教学(4): 函数和MooTools
    用Mootools寫的一个类似facebook的弹出对话框
    用Mootools获得操作索引的两种方法
  • 原文地址:https://www.cnblogs.com/aehyok/p/3325459.html
Copyright © 2011-2022 走看看