使用 Entity Framework Core 时,通过代码自动 Migration
一 介绍
在使用 Entity Framework Core (下面就叫 EF Core 吧)进行开发时,如果模型有变动,我们要在用 EF Core 提供的命令行工具进行手工迁移,然后再运行程序。但是为了效率,我想能不能在程序的入口处进行 Migration 呢?从个人经验来说应该是可以,因为 EF Tool 虽然提供了 CLI 但是它最终也是被程序解析这些命令。下面就开始分析,如何通过代码进行 Migration 。
二 分析
首先我们要先了解,在使用 EF Core 的 CLI 时,要执行两个步骤:
第一步:生成 Migration 文件;
第二步:更新变更项到数据库;
既然是先生成 Migration 文件再更新,那么在 EF Core 里面一定有对应的模块做这件事情。下面我们看一下 EF Core 项目的结构。从中我们确实找到关于 Migration 的模块。在 Migrations/Design 目录的类名称上我们可以看出来,它就是生成 Migration 文件的。这里先到这儿。

找到了生成 Migration 文件的入口,我们再来找一下如何通过代码将这些变更更新到数据库中。
在使用 EF Core 的时候,我们都要通过继承 DbContext 来编写自己的 DbContext 子类。在 DbContext 类中我们找到了一个 Database 属性。如下图所示:

然后查看了 DatabaseFacde 这个类,并没有发现执行迁移相关的函数。通过代码搜索,我在 RelationalDatabaseFacadeExtensions 这个类中有一个 Migration() 扩展方法。通过注释的解析,我也确定了它就是执行 Migration 文件,并将变更更新到数据库。
这两个步骤对应的代码我们都找到了,下面我们就编写一段儿代码,完成自动将模型变更更新到数据库的功能。
public class AutoMigration
{
private readonly IServiceProvider _serviceProvider;
private InformationDbContext _context; public AutoMigration(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
_context = serviceProvider.GetService<InformationDbContext>();
} public void Migrator()
{
var path = Path.Combine(AppContext.BaseDirectory, "..\\..\\..\\Migrations\\");
if (!Directory.Exists(path))
{
Directory.CreateDirectory(path);
}
else
{
Directory.GetFiles(path).ToList().ForEach(File.Delete);
} using (_context)
{
var services = ((IInfrastructure<IServiceProvider>) _context).Instance;
var codeHelper = new CSharpHelper();
var scaffolder = ActivatorUtilities.CreateInstance<MigrationsScaffolder>(services,
new CSharpMigrationsGenerator(codeHelper, new CSharpMigrationOperationGenerator(codeHelper),
new CSharpSnapshotGenerator(codeHelper))); var projectDir = Path.Combine(path, "..\\");
var migrationAssembly = new MigrationsAssembly(new CurrentDbContext(_context), _context.Options, new MigrationsIdGenerator());
scaffolder.GetType().GetField("_migrationsAssembly", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(scaffolder, migrationAssembly); var readonlyDic = new ReadOnlyDictionary<string,TypeInfo>(new Dictionary<string, TypeInfo>());
migrationAssembly.GetType().GetField("_migrations", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(migrationAssembly, new LazyRef<IReadOnlyDictionary<string, TypeInfo>>(readonlyDic));
var migration = scaffolder.ScaffoldMigration("Information.Migrations", "Information"); scaffolder.Save(projectDir, migration, path); //另外一种保存方式
//File.WriteAllText($"Migrations\\{migration.MigrationId}{migration.FileExtension}", migration.MigrationCode);
//File.WriteAllText("Migrations\\" +
// migration.MigrationId + ".Designer" + migration.FileExtension,
// migration.MetadataCode);
//File.WriteAllText("Migrations\\" + migration.SnapshotName + migration.FileExtension,
// migration.SnapshotCode);
} using(_context = (InformationDbContext)_serviceProvider.GetService<IDbContext>())
{
_context.Database.Migrate();
}
}
}
另外一个注意点:我们需要指定一下迁移文件所在项目。
services.AddDbContext<InformationDbContext>(opt =>
{
var connectionString = configuration["ConnectionStrings:DefaultConnection"];
opt.UseSqlServer(connectionString, optionBuilder =>
{
optionBuilder.MigrationsAssembly("Information");
});
});
三 总结
通过上面的分析可以知道,其实我们就是把 CLI 的两个命令通过代码实现了一下。在 Startup 文件中进行调用即可。为什么想这么干?因为在实际开发的时候,来回切换窗口心里觉得不爽了呗。:)
使用 Entity Framework Core 时,通过代码自动 Migration的更多相关文章
- 对Entity Framework Core的一次误会:实体状态不跟踪
在 Entity Framework 中,当通过 EF 使用 LINQ 查询获取到一个实体(实际得到的是 EF 动态生成的实体类的代理类的实例)时,这个实体的状态默认是被跟踪的.所以,当你修改实体的某 ...
- Entity Framework Core 2.0 使用代码进行自动迁移
一.前言 我们在使用EF进行开发的时候,肯定会遇到将迁移更新到生产数据库这个问题,前面写了一篇文章介绍了Entity Framework Core 2.0的入门使用,这里面介绍了使用命令生成迁移所需的 ...
- [转帖]2016年时的新闻:ASP.NET Core 1.0、ASP.NET MVC Core 1.0和Entity Framework Core 1.0
ASP.NET Core 1.0.ASP.NET MVC Core 1.0和Entity Framework Core 1.0 http://www.cnblogs.com/webapi/p/5673 ...
- Entity Framework Core 实现MySQL 的TimeStamp/RowVersion 并发控制
将通用的序列号生成器库 从SQL Server迁移到Mysql 遇到的一个问题,就是TimeStamp/RowVersion并发控制类型在非Microsoft SQL Server数据库中的实现.SQ ...
- 全自动迁移数据库的实现 (Fluent NHibernate, Entity Framework Core)
在开发涉及到数据库的程序时,常会遇到一开始设计的结构不能满足需求需要再添加新字段或新表的情况,这时就需要进行数据库迁移. 实现数据库迁移有很多种办法,从手动管理各个版本的ddl脚本,到实现自己的mig ...
- Entity Framework Core 1.1 Preview 1 简介
实体框架核心(EF Core)是Entity Framework的一个轻量级,可扩展和跨平台版本. 10月25日,Entity Framework Core 1.1 Preview 1发布了. 升级到 ...
- Working with Data » Getting started with ASP.NET Core and Entity Framework Core using Visual Studio » 更新关系数据
Updating related data¶ 7 of 7 people found this helpful The Contoso University sample web applicatio ...
- Working with Data » Getting started with ASP.NET Core and Entity Framework Core using Visual Studio » 读取关系数据
Reading related data¶ 9 of 9 people found this helpful The Contoso University sample web application ...
- Working with Data » Getting started with ASP.NET Core and Entity Framework Core using Visual Studio » 创建复杂数据模型
Creating a complex data model 创建复杂数据模型 8 of 9 people found this helpful The Contoso University sampl ...
随机推荐
- 关于MySql 关键字与字段名冲突 的问题
我在用mysql创建数据表时,其中一个表怎么创建都提示失败,最终我把语句翻来覆去折腾了许多遍之后发现原来我的一个字段值的名称为order的字段出了问题,把它去了就好了,最后结论就是设置字段值名称时不要 ...
- Java 技术文章摘录
sokcet 编程实例 android bundle类 Android -- Looper.prepare()和Looper.loop() —深入版 Java NIO系列教程 XML操作 Androi ...
- X.509证书生成
创建数字证书 用户对数字证书的认可决定于对证书颁发机构的信任,所以证书颁发机构决定了数字证书的可用范围.由于官方认可的数字证书颁发机构,比如VeriSign.Thawte(OpenSSL),具有普遍的 ...
- queue
http://www.codeforces.com/contest/625/problem/E
- Oracle基础笔记
=====================================第一章:oracle数据库基础============================================= Or ...
- Lodop6 以上打印控件使用,详参考自带说明文档,打印样式及文字大小要特殊设置一下
<link href="../css/cssprint.css" rel="stylesheet" /> <script src=" ...
- 在SQL2008配置数据库镜像1418错误的处理
在SQL2008配置数据库镜像错误一般都由以下原因造成 1.主体.镜像服务器SQL SERVER选择本账号切保持一致 2.在数据库镜像配置向导中的“服务账号”选项中请选择需要同步数据库的登陆名,例如数 ...
- springmvc图片文件上传接口
springmvc图片文件上传 用MultipartFile文件方式传输 Controller package com.controller; import java.awt.image.Buffer ...
- 在VMware下正确克隆CentOS6.5的打开方式
引言 想必用VMware Workstation软件安装虚拟机,作为一个爱"折腾"的攻城狮肯定是千千万万遍的事情.无论是学习还是工作之中,我们都会遇到需要在一台物理主机上运行多台虚 ...
- PHP正则表达式模式修饰符 /i, /is, /s, /isU等
模式修饰符 下面列出了当前可用的 PCRE 修饰符.括号中提到的名字是 PCRE 内部这些修饰符的名称. 模式修饰符中的空格,换行符会被忽略,其他字符会导致错误. i (PCRE_CASELESS) ...