参考
- SqlLocalDB 实用工具
在开始测试EF代码迁移之前,先来了解下LocalDB。
我们知道微软有一个SQL Server的免费版本SQL Server Express,它是作为学习以及构建桌面或小型服务器应用的入门级的免费数据库。但是作为编程人员,还是觉得体积过大。所以微软为开发者量身定制了一款专门用于编程开发的小数据库SQL Server Express LocalDB(实际上就是从SQL Server Express中抽离出来的)。
如果采用Visual Studio开发,那么恭喜你Visual Studio从2012版本开始就自带了LocalDB。我当前机器在安装 VS2013的时候默认安装了 LocalDB。
开启当前数据库服务
## vs2013 自带的的localdb版本为 v11.0, vs2017的版本为 v13.0##
$ sqllocaldb start v11.0
## 查看命令帮助 ##
$ sqllocaldb -?
## 创建数据库实例 ##
$ sqllocaldb create ef_test
##查看当前实例列表 ##
$ sqllocaldb info
创建控制台应用
打开VS2013,创建一个控制台应用,当前采用的.net 版本为 v4.5.2
安装nuget引用
Install-Package EntityFramework
当前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=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</configSections>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
</startup>
<entityFramework>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
<parameters>
<parameter value="mssqllocaldb" />
</parameters>
</defaultConnectionFactory>
<providers>
<provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
</providers>
</entityFramework>
</configuration>
创建 Blog.cs 和 DbContext 的派生类 BlogContext.cs
public class Blog
{
public int BlogId { get; set; }
public string Name { get; set; }
}
public class BlogContext : DbContext
{
public DbSet<Blog> Blogs { get; set; }
}
更改 Program.cs 以调用
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);
}
}
Console.WriteLine("Press any key to exit...");
Console.ReadKey();
}
第一次运行程序就通过了,之前的 App.config 中并没有填写任何的连接字符串,数据保存在哪个数据库实例,哪个数据库中,还不是很清楚。
仔细查看 App.config 中的节点 defaultConnectionFactory
中的参数mssqllocaldb
应该是 localdb中的实例名称。用 navicat 打开数据库看看
表Blogs根据业务类生成的库表,数据库字段和类的属性是一一对应的。
__MigrationHistory
MigrationId: 就是在Add-Migration指令中指定的<版本名>,EF会自动在前面加上时间戳
ContextKey: 主要作用是对Model进行分组,这样不同项目的Model可以在同一个DB中互不干扰
Model:EF会基于DBContext中包含的所有Entity Model生成字节数组,核心代码如下所示
ProductVersion:生成这个Migration的EF的版本号
业务类属性有变化怎么办
Blog类多增加了一个属性 Memo
public class Blog
{
public int BlogId { get; set; }
public string Name { get; set; }
//新增加一个字段
public string Memo { get; set; }
}
提示
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).
刚刚在【程序包管理器控制台】中安装EF的时候最后有一段话:
PM> Install-Package EntityFramework
正在安装“EntityFramework 6.2.0”。
您正在从 Microsoft 下载 EntityFramework,有关此程序包的许可协议在 http://go.microsoft.com/fwlink/?LinkID=262998 上提供。请检查此程序包是否有其他依赖项,这些依赖项可能带有各自的许可协议。您若使用程序包及依赖项,即构成您接受其许可协议。如果您不接受这些许可协议,请从您的设备中删除相关组件。
已成功安装“EntityFramework 6.2.0”。
正在将“EntityFramework 6.2.0”添加到 ConsoleApplication1_EF_TEST。
已成功将“EntityFramework 6.2.0”添加到 ConsoleApplication1_EF_TEST。
Type 'get-help EntityFramework' to see all available Entity Framework commands.
接下来再看看 get-help EntityFramework
能获得什么帮助
PM> get-help EntityFramework
TOPIC
about_EntityFramework
SHORT DESCRIPTION
Provides information about Entity Framework commands.
LONG DESCRIPTION
This topic describes the Entity Framework commands. Entity Framework is
Microsoft's recommended data access technology for new applications.
The following Entity Framework cmdlets are used with Entity Framework
Migrations.
Cmdlet Description
----------------- ---------------------------------------------------
Enable-Migrations Enables Code First Migrations in a project.
Add-Migration Scaffolds a migration script for any pending model
changes.
Update-Database Applies any pending migrations to the database.
Get-Migrations Displays the migrations that have been applied to
the target database.
The following Entity Framework cmdlets are used by NuGet packages that
install Entity Framework providers. These commands are not usually used as
part of normal application development.
Cmdlet Description
------------------------------ ---------------------------------------
Add-EFProvider Adds or updates an Entity Framework
provider entry in the project config
file.
Add-EFDefaultConnectionFactory Adds or updates an Entity Framework
default connection factory in the
project config file.
Initialize-EFConfiguration Initializes the Entity Framework
section in the project config file and
sets defaults.
SEE ALSO
Enable-Migrations
Add-Migration
Update-Database
Get-Migrations
Enable-Migrations | Enables Code First Migrations in a project.(启用代码迁移)
上面这个命令应该可以试试
PM> Enable-Migrations
Checking if the context targets an existing database...
Detected database created with a database initializer. Scaffolded migration '201903150554139_InitialCreate' corresponding to existing database. To use an automatic migration instead, delete the Migrations folder and re-run Enable-Migrations specifying the -EnableAutomaticMigrations parameter.
Code First Migrations enabled for project ConsoleApplication1_EF_TEST.
然后检查下 库表Blogs
,没啥变化。
检查下项目,增加了一个文件夹 Migrations,包含两个文件201903150554139_InitialCreate.cs
namespace ConsoleApplication1_EF_TEST.Migrations
{
using System;
using System.Data.Entity.Migrations;
public partial class InitialCreate : DbMigration
{
public override void Up()
{
CreateTable(
"dbo.Blogs",
c => new
{
BlogId = c.Int(nullable: false, identity: true),
Name = c.String(),
})
.PrimaryKey(t => t.BlogId);
}
public override void Down()
{
DropTable("dbo.Blogs");
}
}
}
Configuration.cs
namespace ConsoleApplication1_EF_TEST.Migrations
{
using System;
using System.Data.Entity;
using System.Data.Entity.Migrations;
using System.Linq;
internal sealed class Configuration : DbMigrationsConfiguration<ConsoleApplication1_EF_TEST.BlogContext>
{
public Configuration()
{
AutomaticMigrationsEnabled = false;
ContextKey = "ConsoleApplication1_EF_TEST.BlogContext";
}
protected override void Seed(ConsoleApplication1_EF_TEST.BlogContext 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.
}
}
}
Add-Migration | Scaffolds a migration script for any pending model
changes.(为任何挂起的模型更改提供迁移脚本。)
第一次执行的 Enable-Migrations
是做准备,这里执行Add-Migration
是开始准备给 Blogs表增加字段的脚本了。
#addBlogMemo 是我们给的改动命名
PM> Add-Migration addBlogMemo
Scaffolding migration 'addBlogMemo'.
The Designer Code for this migration file includes a snapshot of your current Code First model. This snapshot is used to calculate the changes to your model when you scaffold the next migration. If you make additional changes to your model that you want to include in this migration, then you can re-scaffold it by running 'Add-Migration addBlogMemo' again.
文件夹 Migrations中又生成了一个新文件:201903150640019_addBlogMemo.cs
namespace ConsoleApplication1_EF_TEST.Migrations
{
using System;
using System.Data.Entity.Migrations;
public partial class addBlogMemo : DbMigration
{
public override void Up()
{
AddColumn("dbo.Blogs", "Memo", c => c.String());
}
public override void Down()
{
DropColumn("dbo.Blogs", "Memo");
}
}
}
此时只是提供了脚本,并没有更改数据库
Update-Database | Applies any pending migrations to the database..(将任何挂起的迁移应用到数据库。)
PM> Update-Database
Specify the '-Verbose' flag to view the SQL statements being applied to the target database.
Applying explicit migrations: [201903150640019_addBlogMemo].
Applying explicit migration: 201903150640019_addBlogMemo.
Running Seed method.
执行Update-Database
后,Blogs表就更新了
__MigrationHistory
表也响应的增加了一条记录
代码迁移完成!