当前位置: 移动技术网 > IT编程>开发语言>.net > Asp.Net Core 轻松学-使用MariaDB/MySql/PostgreSQL和支持多个上下文对象

Asp.Net Core 轻松学-使用MariaDB/MySql/PostgreSQL和支持多个上下文对象

2019年01月22日  | 移动技术网IT编程  | 我要评论

前言

在上一篇文章中(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

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网