Asp.Net Core 輕鬆學-使用MariaDB/MySql/PostgreSQL和支持多個上下文對象

前言

在上一篇文章中(Asp.Net Core 輕鬆學-10分鐘使用EFCore鏈接MSSQL數據庫)[http://www.javashuo.com/article/p-quroiyoe-n.html],介紹了 EFCore 鏈接 MSSQL 的使用方法,在本章中,將繼續介紹如何利用 EFCore 鏈接到 MariaDB/MySql 和 PostgreSQL 數據庫,同時,在一個項目中,如何添加多個數據庫上下文對象,並在業務中使用多個上下文對象,經過這兩章的學習,你將掌握使用 EFCore 鏈接 MSSQL/MariaDB/MySql/PostgreSQL 的能力。在 .NETCore 的時代,因爲其設計的獨特性(區別於.NetFramework),使得咱們很是容易的使用各類開源的、跨平臺的產品和中間件,做爲普通程序員,經過普遍參與和使用開源產品,是咱們責無旁貸的責任和義務,這種行爲將進一步的擴大 .Net Core 的生態圈,進而影響整個開發行業。閒話說完,進入今天的正題,鏈接第三方數據庫和支持多個上下文對象。html

1. 使用 MariaDB/MySql 數據庫

MariaDB基於MySQL並遵循GPL v2受權使用的。 她是由以Monty Program Ab爲主要管理者的MariaDB社區開發的。MariaDB與另外一分支MySQL最新版保持同步更新。在MariaDB工做與在MySQL下工做幾乎如出一轍,她們有相同的命令、界面,以及在MySQL中的庫與API,因此MariaDB能夠說是爲替換MySQL量身定作的,因此它們之間是相通用(兼容),換用後連數據庫都沒必要轉換並能夠得到MariaDB提供的許多更好的新特性。
以上介紹來自官方文檔 https://mariadb.com/kb/zh-cn/mariadb-mariadb/mysql

1.1

首先建立一個 Asp.Net Core WebApi 2.2 的項目 Ron.OtherDB,並從 NuGet 倉庫引用包 Pomelo.EntityFrameworkCore.MySql,我本地安裝的數據庫是 MariaDB,從介紹中得知,MariaDB 和 MySql 的使用方式幾乎是徹底一致的,因此這裏使用 Pomelo.EntityFrameworkCore.MySql 鏈接 MariaDB 也是沒有任何問題的git

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 的使用方式幾乎是沒有什麼不一樣的,可讓開發人員平滑的過渡。github

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。sql

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 的 Demojson

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以及其餘語言等,也包含各類文檔api

以上介紹來自 PostgreSQL 中文社區:http://www.postgres.cn/v2/about,本人公司的主要業務也是基於 .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 分別調用 http://localhost:5000/api/home 中的 GET/POST/PUT/DELETE 接口,能夠看到,數據庫中能夠正常添加和修改數據
  • MariaDB/MySql 數據庫結果

  • PostgreSQL 數據庫結果

從結果中能夠看到,代碼執行正常完成,至此,本文完成

結束語

經過本文學習,咱們掌握瞭如下能力

  • 如何在 Asp.NetCore 中使用 EFCore 鏈接使用 MariaDB/MySql/PostgreSQL 數據庫,
  • 如何建立多個 Migrations 對象
  • 如何在項目中使用多個不一樣的上下文對象

演示代碼下載

https://github.com/lianggx/EasyAspNetCoreDemo/tree/master/Ron.OtherDB

相關文章
相關標籤/搜索