Asp.Net Core 轻松学-使用MariaDB/MySql/PostgreSQL和支持多个上下文对象
前言
在上一篇文章中(asp.net core 轻松学-10分钟使用efcore连接mssql数据库)[],介绍了 efcore 连接 mssql 的使用方法,在本章中,将继续介绍如何利用 efcore 连接到 mariadb/mysql 和 postgresql 数据库,同时,在一个项目中,如何添加多个数据库上下文对象,并在业务中使用多个上下文对象,通过这两章的学习,你将掌握使用 efcore 连接 mssql/mariadb/mysql/postgresql 的能力。在 .netcore 的时代,由于其设计的独特性(区别于.netframework),使得我们非常容易的使用各种开源的、跨平台的产品和中间件,作为普通程序员,通过广泛参与和使用开源产品,是我们义不容辞的责任和义务,这种行为将进一步的扩大 .net core 的生态圈,进而影响整个开发行业。闲话说完,进入今天的正题,连接第三方数据库和支持多个上下文对象。
1. 使用 mariadb/mysql 数据库
mariadb基于mysql并遵循gpl v2授权使用的。 她是由以monty program ab为主要管理者的mariadb社区开发的。mariadb与另一分支mysql最新版保持同步更新。在mariadb工作与在mysql下工作几乎一模一样,她们有相同的命令、界面,以及在mysql中的库与api,所以mariadb可以说是为替换mysql量身定做的,所以它们之间是相通用(兼容),换用后连数据库都不必转换并可以获得mariadb提供的许多更好的新特性。
以上介绍来自官方文档
1.1
首先创建一个 asp.net core webapi 2.2 的项目 ron.otherdb,并从 nuget 仓库引用包 pomelo.entityframeworkcore.mysql,我本地安装的数据库是 mariadb,从介绍中得知,mariadb 和 mysql 的使用方式几乎是完全一致的,所以这里使用 pomelo.entityframeworkcore.mysql 连接 mariadb 也是没有任何问题的
1.2 项目结构和包引用如下
1.3 编写业务实体
下面将编写两个业务实体 topic/post,在本章中,无论是连接 mariadb/mysql 还是 postgresql,都将使用这两个实体对象
public class topic { public int id { get; set; } public string title { get; set; } public string content { get; set; } public datetime createtime { get; set; } public icollection<post> posts { get; set; } } public class post { public int id { get; set; } public int topicid { get; set; } public string content { get; set; } public datetime createtime { get; set; } public topic topic { get; set; } }
1.4 编写上下文对象
public class mysqlforumcontext : dbcontext { public mysqlforumcontext(dbcontextoptions<mysqlforumcontext> options) : base(options) { } public dbset<topic> topics { get; set; } public dbset<post> posts { get; set; } }
该上下文对象非常简单,只是声明了一个 mysqlforumcontext 对象,然后继承自 dbcontext ,并将 topic 和 post 实体对象映射到该上下文中,这个使用方式和之前的文章中连接 mssql 数据库的使用方式是完全一致的,这点非常难得,通过 efcore,无论你连接到的是哪种类型的数据库,其 api 的使用方式几乎是没有什么不同的,可以让开发人员平滑的过渡。
1.5 在 appsetting.json 中配置数据库连接字符串
{ "logging": { "loglevel": { "default": "warning" } }, "allowedhosts": "*", "connectionstrings": { "mysql.forum": "server=127.0.0.1;port=3406;uid=root;pwd=root;database=forum;" } }
本来上面的连接字符串是无需指定端口的,但是因为使用 pomelo.entityframeworkcore.mysql 组件连接 mysql 默认使用的端口是:3306,而我本机上指定端口为 3406,所以还是需要指定 port=3406。
1.6 在 startup.cs 中初始化上下文对象
public void configureservices(iservicecollection services) { services.adddbcontext<mysqlforumcontext>(options => { var connectionstring = this.configuration["connectionstrings:mysql.forum"]; options.usemysql(connectionstring); }); ... }
1.7 创建 migrations 对象
- 在包管理器控制台输入以下命令,创建 migrations 对象
add-migration mysql.forum.v1
- 继续在包管理器控制台中输入以下命令,该命令将会在数据库中创建实体业务对象 topic/post 映射的数据表
update-databse
- 打开 mariadb ,可以看到,数据库已经成功创建
非常完美,到这一步,你已经完成了使用 efcore 连接到 mariadb/mysql 数据库的过程,先不要急做各种 curd 的操作,下面,我们继续在项目中使用 efcore 连接 postgresql 数据库,到最后我们再一起做一个 curd 的 demo
2. 使用 postgresql 数据库
postgresql是一个功能强大的开源数据库系统。经过长达15年以上的积极开发和不断改进,postgresql已在可靠性、稳定性、数据一致性等获得了业内极高的声誉。目前postgresql可以运行在所有主流操作系统上,包括linux、unix(aix、bsd、hp-ux、sgi irix、mac os x、solaris和tru64)和windows。postgresql是完全的事务安全性数据库,完整地支持外键、联合、视图、触发器和存储过程(并支持多种语言开发存储过程)。它支持了大多数的sql:2008标准的数据类型,包括整型、数值值、布尔型、字节型、字符型、日期型、时间间隔型和时间型,它也支持存储二进制的大对像,包括图片、声音和视频。postgresql对很多高级开发语言有原生的编程接口,如c/c++、java、.net、perl、python、ruby、tcl 和odbc以及其他语言等,也包含各种文档
以上介绍来自 postgresql 中文社区: .netcore+mysql+postgresql,在使用 postgresql 的过程中,发现 postgresql 真的是一个非常强大的数据库,对我们的业务带来非常大的帮助,希望大家都能深入的了解和使用 postgresql
2.1 首先还是在项目中引用 npgsql.entityframeworkcore.postgresql 包
2.2 编写上下文对象 npgsqlforumcontext
public class npgsqlforumcontext : dbcontext { public npgsqlforumcontext(dbcontextoptions<npgsqlforumcontext> options) : base(options) { } public dbset<topic> topics { get; set; } public dbset<post> posts { get; set; } }
有没有发现,上下文对象 npgsqlforumcontext 的结构和上面的 mysqlforumcontext 几乎是一模一样的
2.3 在配置文件中增加 postgresql 的连接字符串
{ "logging": { "loglevel": { "default": "warning" } }, "allowedhosts": "*", "connectionstrings": { "mysql.forum": "server=127.0.0.1;port=3406;uid=root;pwd=root;database=forum;", "pgsql.forum": "server=127.0.0.1;port=5432;uid=postgres;pwd=postgres;database=forum;" } }
注意:postgresql 的侦听的默认端口是:5432
2.4 在 startup.cs 中初始化上下文对象
public void configureservices(iservicecollection services) { // mariadb/mysql 上下文初始化 services.adddbcontext<mysqlforumcontext>(options => { var connectionstring = this.configuration["connectionstrings:mysql.forum"]; options.usemysql(connectionstring); }); // postgresql 上下文初始化 services.adddbcontext<npgsqlforumcontext>(options => { var connectionstring = this.configuration["connectionstrings:pgsql.forum"]; options.usenpgsql(connectionstring); }); ... }
2.5 创建 migrations for postgresql 对象
- 这里创建 migrations 的方式和上面的创建 migrations for mariadb/mysql 的方式是一样的,在项目包管理器控制台中输入以下命令,创建 migrations 对象后直接创建数据库
add-migration postgresql.forum.v1 -context npgsqlforumcontext
update-database -context npgsqlforumcontext
== 注意:这里的创建数据库命令和上面创建 mariadb/mysql 的命令有一点小小的不同 ==
因为我们现在是在一个项目里面使用多个上下文对象,在创建 migrations 的时候, ef 会自动查找匹配的 context ,但是,由于使用了多个 context,在执行命令时,必须指定 -context npgsqlforumcontext,否则,将抛出 more than one dbcontext was found. specify which one to use. use the '-context' parameter for powershell commands and the '--context' parameter for dotnet commands. 的异常。
- 打开 postgresql 管理工具,发现数据库 forum 已经成功创建,表结构和 mariadb/mysql 中创建的 forum 数据库表完全一致,使用的都是同一个实体业务对象 topic/post
到这里,我们已经完成了使用 efcore 连接到 postgresql 的过程,在 postgresql 中,由于没有指定 schema ,所以默认数据表会被放在 schema public 下面,有关更多 postgresql 的 schema ,请移步官网进一步了解,如果希望在创建数据库的过程中指定 schema ,可以在实体对象 topic中应用特性 tableattribute 进行标记即可,也可以手动修改 migrations 文件,像下面这样
- 使用特性 tableattribute 进行标记
[table("topic",schema ="blogs")] public class topic { public int id { get; set; } public string title { get; set; } public string content { get; set; } public datetime createtime { get; set; } public icollection<post> posts { get; set; } }
- 手动修改 migrations 文件 migrations/20190119035709_postgresql.forum.v1.cs
// 代码片段,仅需要增加指定 schema:"blogs" 即可 migrationbuilder.createtable( name: "topics", schema: "blogs", columns: table => new { id = table.column<int>(nullable: false) .annotation("npgsql:valuegenerationstrategy", npgsqlvaluegenerationstrategy.serialcolumn), title = table.column<string>(nullable: true), content = table.column<string>(nullable: true), createtime = table.column<datetime>(nullable: false) }, constraints: table => { table.primarykey("pk_topics", x => x.id); });
3. 在项目中使用多个上下文
在 ron.otherdb 项目中,我们一共创建了两个 context ,分别是 mysqlforumcontext 和 npgsqlforumcontext,这两个 context 可以在项目中一起使用,互不影响
3.1 在 homecontroller 注入两个 context
private mysqlforumcontext mysqlcontext; private npgsqlforumcontext pgsqlcontext; public homecontroller(mysqlforumcontext mysqlcontext, npgsqlforumcontext pgsqlcontext) { this.mysqlcontext = mysqlcontext; this.pgsqlcontext = pgsqlcontext; } `` > 注入的方式非常简单,和其它类型的注入使用方式没有区别,就是简单的在 homecontroller 的构造函数中声明这两个 context 对象即可 #####3.2 使用两个上下文对象进行 curd 操作 > 下面将演示使用 mysqlforumcontext 和 npgsqlforumcontext 进行简单的 curd 操作,这个操作过程和上一篇的 mssql 几乎是完全相同的,代码比较简单,就直接贴上来了
[route("api/[controller]"), apicontroller] public class homecontroller : controllerbase { private mysqlforumcontext mysqlcontext; private npgsqlforumcontext pgsqlcontext; public homecontroller(mysqlforumcontext mysqlcontext, npgsqlforumcontext pgsqlcontext) { this.mysqlcontext = mysqlcontext; this.pgsqlcontext = pgsqlcontext; } [httpget] public actionresult get() { // mysql var mysqltopics = this.mysqlcontext.topics.tolist(); // pgsql var pgsqltopics = this.pgsqlcontext.topics.tolist(); return new jsonresult(new { mysql = mysqltopics, pgsql = pgsqltopics }); } [httppost] public async task post([frombody] topicviewmodel model) { // mysql this.mysqlcontext.topics.add(new topic() { content = model.content, createtime = datetime.now, title = model.title }); await this.mysqlcontext.savechangesasync(); // pgsql this.pgsqlcontext.topics.add(new topic() { content = model.content, createtime = datetime.now, title = model.title }); await this.pgsqlcontext.savechangesasync(); } [httpput] public async task put([frombody] topicviewmodel model) { // mysql var topic = this.mysqlcontext.topics.where(f => f.id == model.id).firstordefault(); topic.title = model.title; topic.content = model.content; await this.mysqlcontext.savechangesasync(); // pgsql var pgtopic = this.pgsqlcontext.topics.where(f => f.id == model.id).firstordefault(); pgtopic.title = model.title; pgtopic.content = model.content; await this.pgsqlcontext.savechangesasync(); } [httpdelete("{id}")] public async task delete(int id) { // mysql var topic = this.mysqlcontext.topics.where(f => f.id == id).firstordefault(); this.mysqlcontext.topics.remove(topic); await this.mysqlcontext.savechangesasync(); // pgsql var pgtopic = this.pgsqlcontext.topics.where(f => f.id == id).firstordefault(); this.pgsqlcontext.topics.remove(pgtopic); await this.pgsqlcontext.savechangesasync(); } }
```
3.3 打开控制台执行 dotnet run
3.4 分别调用 中的 get/post/put/delete 接口,可以看到,数据库中可以正常添加和修改数据
- mariadb/mysql 数据库结果
- postgresql 数据库结果
从结果中可以看到,代码执行正常完成,至此,本文完成
结束语
通过本文学习,我们掌握了以下能力
- 如何在 asp.netcore 中使用 efcore 连接使用 mariadb/mysql/postgresql 数据库,
- 如何创建多个 migrations 对象
- 如何在项目中使用多个不同的上下文对象
演示代码下载
https://github.com/lianggx/easyaspnetcoredemo/tree/master/ron.otherdb
上一篇: ASP.Net Core 2.2 MVC入门到基本使用系列 (二)
下一篇: 买酒秘诀