Entity Framework 5.0系列之Code First数据库迁移

简介:

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

Entity Framework配置

在开始今天的话题之前先来看一下Entity Framework的配置,因为有很多朋友因为配置文件的问题造成“Migrations”命令执行失败。

在建立一个应用程序之后我们可以通过在项目上右键“Nuget Packages Manage”进行EF包安装或者直接在“Package Manager Console”中输入“Install-Package EntityFramework”命令进行Entity Framework包安装。这个过程不仅下载并引入了EF框架相关程序集还进行了包的配置和应用用程序配置。下面是这两个配置文件:

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默认的连接配置,只有在没有配置连接字符串时生效。在上一篇文章中我们提到如果不进行连接字符串配置EF会自动识别并创建数据库到“.\SQLEXPRESS”或者“LocalDb”,事实上就是通过这里识别的,可以看出我机器上没有“.\SQLEXPRESS”就自动使用了“LocalDb”,配置默认连接到“LocalDbConnectionFactory”。

在本例中我们需要将连接指向“.\SQL2008”上,有两种方式建立自己的连接:一种是直接配置“defaultConnectionFactory”,将默认生成的“System.Data.Entity.Infrastructure.LocalDbConnectionFactory”改成“System.Data.Entity.Infrastructure.SqlConnectionFactory”,然后在参数中编写我们的连接字符串(注意默认生成的数据库名为“项目名称.数据库上下文名称”)。

<?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.SqlConnectionFactory, EntityFramework">
      <parameters>
        <parameter value="Data Source=.\SQL2008; UID=sa;PWD=123; MultipleActiveResultSets=True" />
      </parameters>
    </defaultConnectionFactory>
  </entityFramework>
</configuration>

另一种是通过传统的 “connectionStrings” 配置,只要配置了连接字符串“defaultConnectionFactory”将不再生效,EF会自动使用该连接。在接下来的示例中我们将采用这种方式。

<?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="CodeFirstDb" connectionString="Data Source=.\SQL2008;Database=CodeFirstDb;UID=sa;PWD=123;MultipleActiveResultSets=true" 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>

Code First数据库迁移

现在让我们在上一篇文章Entity Framework 5.0系列之EF概览中的“Code First”示例的基础上给Order添加一个”Employee”属性,然后运行,不出意外的话你将看到如下异常:

从异常信息我们可以看出,EF已经检测到模型发生了改变,建议我们使用”Code First Migrations”对模型进行更新。事实上EF就是依靠上一篇文章中提到的“dbo.__MigrationHistory”表对我们的模型进行判断的,因为这张表中存储了我们的模型结构(在Model列中),如果运行程序时你跟踪SQL Server会发现EF执行了如下SQL进行模型修改判断:

SELECT Count(*) FROM sys.databases WHERE [name]=N'CodeFirstDb'
go
SELECT TABLE_SCHEMA SchemaName, TABLE_NAME Name FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE'
go
SELECT Count(*) FROM sys.databases WHERE [name]=N'CodeFirstDb'
go
SELECT 
[GroupBy1].[A1] AS [C1]
FROM ( SELECT 
    COUNT(1) AS [A1]
    FROM [dbo].[__MigrationHistory] AS [Extent1]
)  AS [GroupBy1]
go
SELECT TOP (1) 
[Project1].[C1] AS [C1], 
[Project1].[MigrationId] AS [MigrationId], 
[Project1].[Model] AS [Model]
FROM ( SELECT 
    [Extent1].[MigrationId] AS [MigrationId], 
    [Extent1].[Model] AS [Model], 
    1 AS [C1]
    FROM [dbo].[__MigrationHistory] AS [Extent1]
)  AS [Project1]
ORDER BY [Project1].[MigrationId] DESC
go

 

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

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


namespace CodeFirst
{
    public class OrderContext:DbContext
    {
        public OrderContext()
            : base("CodeFirstDb")
        {
        }

        public DbSet<Order> Orders
        {
            get;
            set;
        }

        public DbSet<OrderDetail> OrderDetails
        {
            get;
            set;
        }
    }
}

下面我们将借助于”Code First Magrations” 进行模型更新。

在Visual Studio中执行:Tools->Library Package Manager->Package Manager Console来打开包管理命令行:

在命令行中输入“Enable-Migrations -StartUpProjectName CodeFirst”然后回车(“CodeFirst”是你的项目名称,如果在“Package Manager Console”中选择了默认项目可以不设置“-StartUpProjectName”参数;如果多次执行此命令可以添加-Force参数):

 

注意:如果在运行“Enable-Migrations -StartUpProjectName CodeFirst”命令过程中收到如下错误,请尝试下面给出的方法:

Enable-Migrations : The term 'Enable-Migrations' is not recognized as the name of a cmdlet, function, script file, or operable 
program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.

1. 在Package Manager Console中执行命令:Import-Module F:\[7]CSharp\EntityFramework\CodeFirst\packages\EntityFramework.5.0.0\tools\EntityFramework.PS3.psd1(后面的路径按照你EF包的实际位置修改,这个问题是由于没有导入相应命令造成的)

2. 执行“Install-Package EntityFramework -IncludePrerelease命令重新安装最新版EF(也可以通过-Version参数指定具体版本)。

3. 更新Nuget,具体更新步骤见Installing NuGet

4. 另外,命令执行过程中其他错误可以按照错误提示解决。

如果没有错误你的项目中将自动生成一个名为”Migrations“的文件夹,里面包含两个文件: Configuration.cs和201308211510117_InitialCreate.cs(201308211510117是时间戳)。

Configuration.cs:是迁移配置代码,一般我们不需要修改。

namespace CodeFirst.Migrations
{
    using System;
    using System.Data.Entity;
    using System.Data.Entity.Migrations;
    using System.Linq;

    internal sealed class Configuration : DbMigrationsConfiguration<CodeFirst.OrderContext>
    {
        public Configuration()
        {
            AutomaticMigrationsEnabled = true;
        }

        protected override void Seed(CodeFirst.OrderContext 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" }
            //    );
            //
        }
    }
}

201308211510117_InitialCreate.cs:以代码的形式记录了本地数据库的表结构定义。

namespace CodeFirst.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(),
                        UnitPrice = 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");
        }
    }
}

 

现在在” Package Manager Console”中执行“Add-Migration AddEmployee”命令,该命令会自动比较模型和当前数据库中的表结构,然后执行“AddEmployee”添加一个”Employee”列,此时在”Migrations“文件夹会生成一个名为“201308240757094_AddEmployee.cs”的类(201308240757094是时间戳):

201308240757094_AddEmployee.cs内容如下:

namespace CodeFirst.Migrations
{
    using System;
    using System.Data.Entity.Migrations;
    
    public partial class AddEmployee : DbMigration
    {
        public override void Up()
        {
            AddColumn("dbo.Orders", "Employee", c => c.String());
        }
        
        public override void Down()
        {
            DropColumn("dbo.Orders", "Employee");
        }
    }
}

从这个类中我们可以看出事实上是给“Order”添加了“Employee”列,当然我们也可以手动修改这个类。

接下来,在“Package Manager Console”中执行“Update-Database -StartUpProjectName CodeFirst –Verbose”命令(添加-Verbose参数可以查看到更新脚本),进行数据库结构更新:

此时查看数据库,发现“Order”表已经多了一列:

OK,今天我们的内容就先到此,关于如何根据数据库生成代码类及其更多内容我们在后面的文章中再一起探讨。

目录
相关文章
|
3月前
|
弹性计算 关系型数据库 数据库
手把手带你从自建 MySQL 迁移到云数据库,一步就能脱胎换骨
阿里云瑶池数据库来开课啦!自建数据库迁移至云数据库 RDS原来只要一步操作就能搞定!点击阅读原文完成实验就可获得一本日历哦~
|
21天前
|
算法 大数据 数据库
云计算与大数据平台的数据库迁移与同步
本文详细介绍了云计算与大数据平台的数据库迁移与同步的核心概念、算法原理、具体操作步骤、数学模型公式、代码实例及未来发展趋势与挑战。涵盖全量与增量迁移、一致性与异步复制等内容,旨在帮助读者全面了解并应对相关技术挑战。
32 3
|
2月前
|
存储 SQL 关系型数据库
一篇文章搞懂MySQL的分库分表,从拆分场景、目标评估、拆分方案、不停机迁移、一致性补偿等方面详细阐述MySQL数据库的分库分表方案
MySQL如何进行分库分表、数据迁移?从相关概念、使用场景、拆分方式、分表字段选择、数据一致性校验等角度阐述MySQL数据库的分库分表方案。
391 15
一篇文章搞懂MySQL的分库分表,从拆分场景、目标评估、拆分方案、不停机迁移、一致性补偿等方面详细阐述MySQL数据库的分库分表方案
|
2月前
|
SQL Java 数据库连接
数据库迁移不再难:Flyway 与 Liquibase 大比拼,哪个才是你的真命天子?
【9月更文挑战第3天】数据库迁移在软件开发中至关重要,尤其在使用 ORM 框架如 Hibernate 时。为确保部署时能顺利应用最新的数据库变更,开发者常使用自动化工具。Flyway 和 Liquibase 是当前流行的两种选择,均能有效管理数据库版本控制。Flyway 采用 SQL 脚本表示变更,简单易用;Liquibase 支持多种脚本格式,功能更强大,适合复杂项目。本文将对比这两种工具的特点,并通过示例展示各自的优缺点,帮助开发者根据项目需求做出合适的选择。
455 1
|
3月前
|
数据库 C# 开发者
WPF开发者必读:揭秘ADO.NET与Entity Framework数据库交互秘籍,轻松实现企业级应用!
【8月更文挑战第31天】在现代软件开发中,WPF 与数据库的交互对于构建企业级应用至关重要。本文介绍了如何利用 ADO.NET 和 Entity Framework 在 WPF 应用中访问和操作数据库。ADO.NET 是 .NET Framework 中用于访问各类数据库(如 SQL Server、MySQL 等)的类库;Entity Framework 则是一种 ORM 框架,支持面向对象的数据操作。文章通过示例展示了如何在 WPF 应用中集成这两种技术,提高开发效率。
55 0
|
3月前
|
Java 前端开发 Spring
技术融合新潮流!Vaadin携手Spring Boot、React、Angular,引领Web开发变革,你准备好了吗?
【8月更文挑战第31天】本文探讨了Vaadin与Spring Boot、React及Angular等主流技术栈的最佳融合实践。Vaadin作为现代Java Web框架,与其他技术栈结合能更好地满足复杂应用需求。文中通过示例代码展示了如何在Spring Boot项目中集成Vaadin,以及如何在Vaadin项目中使用React和Angular组件,充分发挥各技术栈的优势,提升开发效率和用户体验。开发者可根据具体需求选择合适的技术组合。
69 0
|
3月前
|
API Java 开发框架
【从零到精通】如何用Play Framework快速构建RESTful API?看完这篇你就懂了!
【8月更文挑战第31天】《Play Framework快速入门:从零开始构建RESTful API》介绍了如何使用高性能Web开发框架Play Framework构建简单的RESTful API。从环境搭建到项目创建,再到实现用户列表的增删查功能,本文档详细指导每个步骤,并解释核心概念。适合初学者快速上手。首先确保已安装JDK和sbt,然后通过sbt创建Play项目,接着定义控制器、模型及路由,最后运行应用进行测试。通过本教程,你将掌握构建RESTful API的基础知识,为进一步学习Play Framework打下坚实基础。
50 0
|
3月前
|
SQL 关系型数据库 数据库连接
Entity Framework Core 入门教程来袭!快速上手强大的 ORM 工具,开启高效数据库开发之旅!
【8月更文挑战第31天】Entity Framework Core(EF Core)是一个轻量且可扩展的对象关系映射(ORM)框架,允许开发者使用 .NET 语言操作数据库而无需直接编写 SQL 语句。本教程涵盖 EF Core 的安装、数据库上下文创建、数据库连接配置及常见数据库操作(如添加、查询、更新和删除),并介绍如何利用数据库迁移功能安全地更改数据库结构。通过本教程,你可以快速掌握 EF Core 的基本用法,提高开发效率。
69 0
|
3月前
|
SQL Oracle 关系型数据库
Entity Framework Core 实现多数据库支持超厉害!配置连接、迁移与事务,开启多元数据库之旅!
【8月更文挑战第31天】在现代软件开发中,为了满足不同业务需求及环境要求,常需支持多个数据库系统。Entity Framework Core(EF Core)作为一款强大的对象关系映射(ORM)框架,通过数据库提供程序与多种数据库如SQL Server、MySQL、PostgreSQL、Oracle等交互。开发者可通过安装相应NuGet包并配置`DbContextOptionsBuilder`来指定不同数据库连接,从而实现多数据库支持。
182 0
|
7天前
|
SQL 关系型数据库 MySQL
go语言数据库中mysql驱动安装
【11月更文挑战第2天】
20 4