浅谈 EF CORE 迁移和实例化的几种方式
出于学习和测试的简单需要,使用 Console 来作为 EF CORE 的承载程序是最合适不过的。今天笔者就将平时的几种使用方式总结成文,以供参考,同时也是给本人一个温故知新的机会。因为没有一个完整的脉络,所以也只是想起什么写点什么,不通顺的地方还请多多谅解。
本文对象数据库默认为 VS 自带的 LocalDB
- Normal & Simple
先介绍一种最简单的构建方式,人人都会。
新建 Console 应用程序,命名自定
安装相关Nuget 包
//Sql Server Database Provider
Install-Package Microsoft.EntityFrameworkCore.SqlServer
//提供熟悉的Add-Migration,Update-Database等Powershell命令,不区分关系型数据库类型
Install-Package Microsoft.EntityFrameworkCore.Tools
- 自定义 DbContext
public class MyContext:DbContext
{
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer("Server=(localdb)\\mssqllocaldb;Database=ConsoleApp;Trusted_Connection=True;MultipleActiveResultSets=true;");
}
}
- 执行迁移和更新命令
Add-Migration Initialize
Update-Database
- 使用方式
using (var context = new MyContext())
{
// TODO
}
刚以上,我们便见识到了了一种最平常也是最简单的使用方式,接下来,让我们用其他方式去慢慢地改造它,从而尽可能地接触更多的用法。
- Level Up
2.1 准备工作
将第一步生成的数据库,迁移文件和使用方式内容全部删除。
2.2 更新 MyContext 内容
删除 MyContext 中的 OnConfiguring 方法及其内容,增加含有 DbContextOptions 类型参数的构造器,我们的MyContext看起来应该是下面这个样子。
public class MyContext : DbContext
{
public MyContext(DbContextOptions options) : base(options)
{
}
}
假如我们此时仍然再执行迁移命令,VS将提示以下错误
No parameterless constructor was found on 'MyContext'. Either add a parameterless constructor to 'MyContext' or add an implementation of 'IDbContextFactory' in the same assembly as 'MyContext'.
添加无参构造器的方式之后再讲解,先来按照提示信息添加一个 IDbContextFactory 的实现类。
public class MyContextFactory : IDbContextFactory<MyContext>
{
public MyContext Create(DbContextFactoryOptions options)
{
var optionsBuilder = new DbContextOptionsBuilder<MyContext>();
optionsBuilder.UseSqlServer("Server=(localdb)\\mssqllocaldb;Database=ConsoleApp;Trusted_Connection=True;MultipleActiveResultSets=true;");
return new MyContext(optionsBuilder.Options);
}
}
之后再次运行迁移和更新数据库的命令也是水到渠成。
2.3 使用方式:构造器实例化
既然 MyContext 含有 DbContextOptions 类型参数的构造器,那就手动创建一个参数实例注入即可。
var contextOptionsBuilder = new DbContextOptionsBuilder<MyContext>();
contextOptionsBuilder.UseSqlServer("Server=(localdb)\\mssqllocaldb;Database=ConsoleApp;Trusted_Connection=True;MultipleActiveResultSets=true;");
// 注入配置选项
using (var context = new MyContext(contextOptionsBuilder.Options))
{
// TODO
}
经此,我们知道了迁移命令会检测 Context 的相关配置入口,只有在满足存在 OnConfiguring 方法或者存在自建 IDbContextFactory 实现类的情况下,命令才能成功运行。
- Day Day Up
目前为止,我们已经知道如何手动迁移和实例化 Context 的步骤了所以让我们更进一步。写过 ASP.NET CORE 的人可能知道在 ASP.NET CORE 中,Context 常常以依赖注入的方式引入到我们的 Web 层,Service 层,或者 XXCore 层中(话说笔者最近最喜欢的解决方案开发架构就是伪 DDD 的四层架构,有空再介绍吧)。其实在 Console 应用中,这也可以很容易实现,具体的依赖注入引入可以参考笔者的上一篇博客,所以最终的代码效果如下:
var serviceCollection = new ServiceCollection();
serviceCollection.AddDbContext<MyContext>(c =>
{
c.UseSqlServer("Server=(localdb)\\mssqllocaldb;Database=ConsoleApp;Trusted_Connection=True;MultipleActiveResultSets=true;");
});
var serviceProvider = serviceCollection.BuildServiceProvider();
using (var context = serviceProvider.GetService<MyContext>())
{
//context.Database.Migrate();
}
至此,我们便基本完成了本文的主题,唯一有些美中不足的是我们的数据库连接字符串好像到处都是,这不是什么大问题,笔者直接将 Configuration 的配置代码贴在下面,这也是 ABP 中的方式。
public class AppConfigurations
{
private static readonly ConcurrentDictionary<string, IConfigurationRoot> ConfigurationCache;
static AppConfigurations()
{
ConfigurationCache = new ConcurrentDictionary<string, IConfigurationRoot>();
}
public static IConfigurationRoot Get(string environmentName = null)
{
var cacheKey = "#" + environmentName;
return ConfigurationCache.GetOrAdd(
cacheKey,
_ => BuildConfiguration(environmentName)
);
}
private static IConfigurationRoot BuildConfiguration(string environmentName = null)
{
var builder = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", true, true);
if (!string.IsNullOrWhiteSpace(environmentName))
builder = builder.AddJsonFile($"appsettings.{environmentName}.json", true);
builder = builder.AddEnvironmentVariables();
return builder.Build();
}
}
这个工具类的使用方式就不再赘述了。
- 结尾
最后,想必会有人问为什么要折腾这样一个小小的 Console 应用呢?其实通过这样一步步下来,我们可以发现一些项目功能上的亮点,比如既然可以自配置 DbContext 的 Option 选项,同时我们也知道了如何在类库和 Console 项目中添加依赖注入以及 Configuration 提取链接参数的功能,那针对三层架构或是 DDD 项目增加含真实数据库或是内存数据库(InMemory)的单元测试,或者是自动Migrate Context 和更新数据库也将是十分简单的一件事,至少看起来会比官方的示例更加真实和具有可操作性。而这部分内容笔者也将会在之后的博文中给出。
我的博客即将搬运同步至腾讯云+社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan
浅谈 EF CORE 迁移和实例化的几种方式的更多相关文章
- 【ASP.NET MVC系列】浅谈ASP.NET 页面之间传值的几种方式
ASP.NET MVC系列文章 [01]浅谈Google Chrome浏览器(理论篇) [02]浅谈Google Chrome浏览器(操作篇)(上) [03]浅谈Google Chrome浏览器(操作 ...
- [OpenSource]浅谈.Net和Java互相调用的三种方式
在很多的大型系统开发中,开发工具往往不限制于同一种开发语言,而是会使用多种开发语言的混合型开发.目前Java和.Net都声称自己占85%的市场份额,不管谁对谁错,Java和.Net是目前应用开发的两个 ...
- 浅谈.Net和Java互相调用的三种方式
在很多的大型系统开发中,开发工具往往不限制于同一种开发语言,而是会使用多种开发语言的混合型开发.目前Java和.Net都声称自己占85%的市场份 额,不管谁对谁错,Java和.Net是目前应用开发的两 ...
- Cookies 初识 Dotnetspider EF 6.x、EF Core实现dynamic动态查询和EF Core注入多个上下文实例池你知道有什么问题? EntityFramework Core 运行dotnet ef命令迁移背后本质是什么?(EF Core迁移原理)
Cookies 1.创建HttpCookies Cookie=new HttpCookies("CookieName");2.添加内容Cookie.Values.Add(&qu ...
- Spring中bean实例化的三种方式
之前我已经有好几篇博客介绍Spring框架了,不过当时我们都是使用注解来完成注入的,具体小伙伴可以参考这几篇博客(Spring&SpringMVC框架案例).那么今天我想来说说如何通过xml配 ...
- Spring bean管理器 bean实例化的三种方式
bean实例化的三种方式实现 第一种:使用类的无参数构造方法创建(常用 重要) 第一种实例化方式最常用,实例化类时会通过调用无参构造方法创建.示例代码如下: package spring.com.Us ...
- 【Spring】的【bean】管理(XML配置文件)【Bean实例化的三种方式】
Bean实例化的三种方式 说明:通过配置文件创建对象就称为Bean实例化. 第一种:使用类的无参构造创建(重点) 实体类 package com.tyzr.ioc; public class User ...
- 再谈EF Core内存数据库单元测试问题
(此文章同时发表在本人微信公众号"dotNET每日精华文章",欢迎右边二维码来关注.) 题记:在用EF Core的内存数据库进行单元测试的时候遇到"无法访问已释放的对象& ...
- 浅谈.Net Core中使用Autofac替换自带的DI容器
为什么叫 浅谈 呢?就是字面上的意思,讲得比较浅,又不是不能用(这样是不对的)!!! Aufofac大家都不陌生了,说是.Net生态下最优秀的IOC框架那是一点都过分.用的人多了,使用教程也十分丰富, ...
随机推荐
- iOS的内存分析和内存管理
iOS的内存分析和内存管理 [内存管理]一直是iOS开发中的一个重点. 本文就带你从内存分析开始一步步了解内存的占用情况,从真实的情况中领悟真正项目开发过程中的内存的使用情况. 注:本文默认你熟悉 M ...
- C++获取系统当前时间
1.利用系统函数,不仅可以查看系统时间,而且还能修改系统时间 #include<stdlib.h> #include<iostream> using namespace std ...
- --css 控制文字多使用省略号
--css 控制文字多使用省略号.overflowPoint{ text-overflow:ellipsis;width: 200px;overflow: hidden;}<div class= ...
- jquery判断按钮是否被选中了
<script type="text/javascript"> function genjin_view2(elm){ if($(elm).attr("che ...
- 在CentOS7上使用systemctl配置tomcat
最近买了一台阿里云,现在阿里云CentOS都已经支持7了(前面都是使用CentOS6),索性直接使用CentOS7,7上面目前最大区别就是service变成了现在的systemctl,简单的查了一下并 ...
- [leetcode-543-Diameter of Binary Tree]
Given a binary tree, you need to compute the length of the diameter of the tree. The diameter of a b ...
- static方法和非static方法的区别
●生命周期(Lifecycle):静态方法(Static Method)与静态成员变量一样,属于类本身,在类装载的时候被装载到内存(Memory),不自动进行销毁,会一直存在于内存中,直到JVM关闭. ...
- 微信支付(APP)
折腾了一天,终于搞定了微信支付,总结一下.首先从服务器端获取prepareid,Andorid 端再根据这个prepareid二次签名. 服务器端: 从官网上下载DEMO,Demo中只有JsAPi,M ...
- 再谈AbstractQueuedSynchronizer:基于AbstractQueuedSynchronizer的并发类实现
公平模式ReentrantLock实现原理 前面的文章研究了AbstractQueuedSynchronizer的独占锁和共享锁,有了前两篇文章的基础,就可以乘胜追击,看一下基于AbstractQue ...
- Backbone中父子view之间的值传递
backbone中,使用最多的莫过于在view中进行操作,如模板的渲染以及事件函数的定义.为了提高代码的可维护性,一般地我们会写多个视图即view,将界面按照功能的不同进行模块化划分,模块与view一 ...