我们知道无论是“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,今天我们的内容就先到此,关于如何根据数据库生成代码类及其更多内容我们在后面的文章中再一起探讨。

Entity Framework 5.0系列之Code First数据库迁移相关推荐

  1. Entity Framework 5.0系列之约定配置

    Code First之所以能够让开发人员以一种更加高效.灵活的方式进行数据操作有一个重要的原因在于它的约定配置.现在软件开发越来复杂,大家也都试图将软件设计的越来越灵活,很多内容我们都希望是可配置的, ...

  2. 在Entity Framework 4.0中使用 Repository 和 Unit of Work 模式

    [原文地址]Using Repository and Unit of Work patterns with Entity Framework 4.0  [原文发表日期] 16 June 09 04:0 ...

  3. 转载:ADO.NET Entity Framework 试水系列索引(2008/9/9更新,本系列结束)

    Visual Studio 2008发布时,微软给我们带来了LinQ to SQL,解决所谓"阻抗不匹配"问题.最近,随着Visual Studio 2008 SP1的正式发布,又 ...

  4. Log4j 2再现新漏洞;缺乏资助不是开源软件安全的唯一问题;微软公布 Entity Framework 7.0 计划 | 开源日报

    整理 | 宋彤彤 责编 | 屠敏 开源吞噬世界的趋势下,借助开源软件,基于开源协议,任何人都可以得到项目的源代码,加以学习.修改,甚至是重新分发.关注「开源日报」,一文速览国内外今日的开源大事件吧! ...

  5. 浅析Entity Framework Core2.0的日志记录与动态查询条件

    前言 Entity Framework Core 2.0更新也已经有一段时间了,园子里也有不少的文章.. 本文主要是浅析一下Entity Framework Core2.0的日志记录与动态查询条件 去 ...

  6. Entity Framework 5.0基础系列

    1.Entity Framework简介 http://www.cnblogs.com/aehyok/p/3315991.html 2.Entity Framework DBFirst尝试http:/ ...

  7. 深入解读 Entity Framework 4.0和4.1

    记得去年初就开始关注Entity Framework,那时只是简单测试了一下,发现较之Nhibernate不太成熟.当时的EF主要表驱动方式开发,过度依赖edm文件,并且数据层耦合了模型层,让一些MV ...

  8. Entity Framework 6 Alpha 3为Code First提供对存储过程支持,并提供连接恢复功能

    Microsoft宣布Entity Framework 6 Alpha 3已 经可以下载了,它现在支持通过Fluent API将Code First映射到对应的新增.修改和删除功能的存储过程:添加了连 ...

  9. MySql 使用 EF Core 2.0 CodeFirst、DbFirst、数据库迁移(Migration)介绍及示例

    dotnet core 2.0 发布已经好几天了,期间也把原来 dotnet core 1.1 的 MVC 项目升级到了 2.0,升级过程还是比较顺利的,变动也不是太多.升级的过程中也少不了 Enti ...

最新文章

  1. FastDFS安装与使用
  2. 秒懂晶振以及晶振电路 让你从“吃瓜群众”到“技术大牛”
  3. 用ABAP代码实现从1累加到100
  4. ubuntu下如何设置apache的启动和重启
  5. python 常用内置函数
  6. 你抢的不是春节红包而是云!
  7. redistemplate hash 过期时间_Redis过期监听——订单超时-取消
  8. C#类、方法的访问修饰符
  9. 计算机环模实验报告,误差配套实验报告
  10. 周记——20150817
  11. 两个PDF比较标出差异_一分钟学懂快速比较两个PPT文档差异技巧!
  12. 时间管理-重要与紧急
  13. echarts 折线图 中有两条线 ,在鼠标悬停时显示数据
  14. 禅说派-全图型PPT之图片处理技巧精粹
  15. LF-YOLO: A Lighter and Faster YOLO for Weld Defect Detection of X-ray Image
  16. Kubernetes Downward API 基本用法
  17. Linux服务器配置静态IP地址方法
  18. 【液体倒进电脑了怎么办:个人处理经验】
  19. Python界面编程第八课:Pyside2 (Qt For Python)打开关于窗口
  20. RabbitMQ学习笔记 - mandatory参数

热门文章

  1. 利用java实现浏览器功能 jdic
  2. Cartographer源码阅读(4):Node和MapBuilder对象2
  3. linux 批量进行:解压缩某一类压缩文件类型的文件
  4. [linux/ unix] 查看占用端口的 进程ID 的区别
  5. C++ Primer Plus 读书笔记(第4、5章)
  6. php使用 memcache 来存储 session
  7. [C++]##(两个井号)和#(一个井号)都是什么意思
  8. Q132:PBRT-V3,BSSRDF(双向散射表面反射分布函数)(5.6.2章节、11.4章节)
  9. Q87:间接光照(Indirect Illumination)的高光反射(Glossy Reflcetion)
  10. vim python3开发环境_[宜配屋]听图阁 - ubuntu16.04制作vim和python3的开发环境