國產化之路-統信UOS + Nginx + Asp.Net MVC + EF Core 3.1 + 達夢DM8實現簡單增刪改查操作

千島偏舟發表於2020-10-05

專題目錄

國產化之路-統信UOS作業系統安裝
國產化之路-國產作業系統安裝.net core 3.1 sdk
國產化之路-安裝WEB伺服器
國產化之路-安裝達夢DM8資料庫
國產化之路-統信UOS + Nginx + Asp.Net MVC + EF Core 3.1 + 達夢DM8實現簡單增刪改查操作

引言

經過前期的準備工作,.net core 3.1的執行環境和WEB伺服器已經搭建完畢,這裡需要注意一下,達夢DM8資料庫對於Entity Framework Core 3.1 的驅動在NuGet官方源上並沒有正式釋出,需要從Win64安裝版本中的drivers/dotNet提取,這裡需要事先準備。

建立專案

出於開發的習慣和便利性,專案的開發和除錯都還是在windows的環境下面進行,開啟Visual Studio 2019,建立新專案,使用ASP.NET Core web應用程式模板,專案名稱自己取一下,我這裡取名DmExample,版本選擇ASP.NET Core 3.1為HTTPS 配置勾選去掉,暫時不需要HTTPS

點選”建立“按鈕後,稍微等待一會兒,預設的MVC專案搭建完成。在Controllers目錄下只有一個HomeController.cs檔案,點選執行看一下:

已經可以正常跑起來,接下來我們要在這個基礎下開始新增模型、連線達夢資料庫、建立資料庫、新增簡單的增刪改查的操作。

新增驅動

在新增應用之前,為了能夠連線資料庫和建立表,我們首先要使用NuGet包管理工具,安裝如下支援包:

Microsoft.EntityFrameworkCore

Microsoft.EntityFrameworkCore.Tools

Microsoft.EntityFrameworkCore.Design

安裝完以上包後,我們需要安裝EF Core的達夢資料庫驅動,前面提到過在官方的NuGet源中並沒有達夢的EF Core驅動,但在達夢的安裝盤上有提供,所以需要對NuGet包管理器的程式包源進行新增設定,將達夢資料庫安裝源中的EFCore.Dm3.1DmProvider作為包源引入,然後再安裝。

在NuGet包管理器中,點選右上角(紅框框起來的齒輪圖示),彈出選項視窗:

點選視窗右上角的加號圖示,然後名稱輸入EFCore.Dm3.1,源路徑選擇你光碟映象下面的source\drivers\dotNet\EFCore.Dm3.1。以同樣的方式將DmProvider包源引入,源路徑:source\drivers\dotNet\DmProvider,包源設定完成後就可以安裝。

如上圖所示,選擇程式包源EFCore.Dm3.1後,在瀏覽皮膚中會列出達夢的EntityFramework Core的驅動包,選擇它然後點選”安裝“。

同樣,選擇程式包源DmProvider後,在瀏覽皮膚中會列出達夢的DmProvider的驅動包,選擇它然後點選”安裝“。這裡有個地方需要注意,在NuGet包源上可以搜尋到DmProvider 2.0版本的包,雖然版本高於我們當前的本地版本,但這個是.NetFramework版本的,於2017年9月7日釋出,不適用於Core版本的,請不要安裝或更新。

新增模型

驅動安裝完成後,我們要新增一個資料模型,在Models目錄下新增一個User.cs使用者模型,具體程式碼如下:

using System;
using System.ComponentModel.DataAnnotations;

namespace DmExample.Models
{
    /// <summary>
    /// 使用者模型
    /// </summary>
    public class User
    {
        public User()
        {
            Id = Guid.NewGuid().ToString("N");
            CreateTime = DateTime.Now;
        }

        [Key]
        public string Id { get; set; }

        /// <summary>
        /// 姓名
        /// </summary>
        public string Name { get; set; }

        /// <summary>
        /// 年齡
        /// </summary>
        public int? Age { get; set; }

        /// <summary>
        /// 性別
        /// </summary>
        public bool? Gender { get; set; }

        /// <summary>
        /// 建立日期
        /// </summary>
        public DateTime? CreateTime { get; set; }
    }
}

屬性不多,就ID、姓名、年齡、性別、建立日期,分別使用了字串、整型、布林型和日期型別,對一些常規性的屬性做一下資料表屬性對應測試。

建立資料庫

新增資料庫上下文

在專案中新增DbContext目錄,在目錄中新增一個名為DmContext.cs的類作為達夢資料庫上下文,具體程式碼如下:

using DmExample.Models;
using Microsoft.EntityFrameworkCore;

namespace DmExample.DbContext
{
    /// <summary>
    /// 達夢資料庫上下文
    /// </summary>
    public class DmContext : Microsoft.EntityFrameworkCore.DbContext
    {
        /// <summary>
        /// 使用者
        /// </summary>
        public DbSet<User> Users { get; set; }

        public DmContext(DbContextOptions<DmContext> options) : base(options)
        {
        }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);

            modelBuilder.Entity<User>().ToTable("sys_user");
        }
    }
}

如上程式碼所示,DmContext繼承自Microsoft.EntityFrameworkCore.DbContext,新增了使用者UserDbSet,過載OnModelCreating方法,將User模型與資料庫的sys_user表建立對映關係,當然也可以不指定對映關係,在不指定的情況下,預設對映成Users資料表。目前我們還沒建立資料庫,資料庫裡也還沒有這個資料表,接下來需要配置資料庫連線。

配置資料庫連線

(1)新增資料庫連線字串

開啟專案中的appsettings.json配置檔案,新增資料庫連線字串,如下所示:

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*",
  "ConnectionStrings": {
    "DmExample": "Server=localhost;Database=DmExampleDB;User=SYSDBA;Password=111111;"
  }
}

我們在appsettings.json配置檔案中新增了一個ConnectionStrings的配置項,用來設定資料庫連線字串,連線字串命名為DmExample,字串的格式同我們連線SqlServer類似,Server為資料庫地址、Database為資料庫名稱、UserPassword分別為連線資料庫賬號和密碼,需要注意的一點是設定資料庫地址的時候如果是本地地址,我們們往往習慣性地用Server=.來表示,但是達夢資料庫不認識這種表示,會無法連線資料庫,需要把點替換成localhost127.0.0.1才行,這個注意一下。

(2)註冊資料庫上下文

完成資料庫連線字串的新增後,我們需要在Starup.cs類中對當前的資料庫上下文進行註冊,微軟已經為我們提供上下文註冊的中介軟體,只要呼叫它就可以了,具體程式碼如下:

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllersWithViews();

    // 註冊DbContext
    services.AddDbContext<DmContext>(options =>
	options.UseDm(Configuration.GetConnectionString("DmExample")));
}

如上程式碼所示,DmContext是我們們建立的達夢資料庫上下文,DmExample是我們在appsettings.json配置檔案中新增的資料庫連線字串,通過Configuration.GetConnectionString方法獲取該資料庫連線字串。這裡注意這個程式碼:options.UseDm,我們連線SqlServer資料庫的時候是使用options.UseSqlServer,如果我們以後連線MySql資料庫時是使用options.UseMySQL,使用不同的資料庫需要對應的資料庫驅動,UseDm就是由達夢資料庫驅動提供的方法,至此資料庫的連線我們已配置完成,接下來我們要建立資料庫。

建立資料庫

資料庫連線配置完成後,我們直接使用Visual Studio 2019的程式包管理器控制檯,通過命令方式來建立資料庫,首先輸入如下命令(initDB是我們取的名字,沒有強制規定):

add-migration 'initDB'

The add-migration command is one of the key commands in code first migrations. When you make changes to your domain model and need them dded into your database you create a new migration. This is done with the Add-Migration command. In it’s simplest form you need only toprovide a migration name.

add-migration命令是code first migration中的關鍵命令之一。當您對領域域模型進行更改並需要將它們時新增到資料庫中,您將建立一個新的遷移。這是通過Add-Migration命令完成的。用最簡單的形式,你只需要提供遷移名稱。

命令執行成功後會在當前的專案中建立Migrations目錄, 在這個目錄中我們發現有兩個檔案,其中一個檔案由當前建立日期加上我們之前add 後面建立名字的一個記錄20201002080053_initDB記錄了此次更新的部分,由於我們是第一次初始化,所以裡面記錄了全部表結構內容,下次我們再次使用該命令做更新時,會再次新增新的記錄檔案,只記錄更新部分;另一個名為 DmContextModelSnapshot的檔案是 Migrations生成的IModel狀態的快照的基類,裡面記錄了要生成db的內容。

接下來執行更新資料庫命令:

update-database

出現如上圖所示表示執行成功,為驗證是否建立資料表,我們開啟達夢的資料庫管理工具,檢視資料庫是否已存在:

我們在模式->SYSDBA->表下面發現了sys_user這張表,在表空間->MAIN->表也能夠看到這張表。資料表應該是建立成功了,但是就是沒有發現我們在資料庫連線字串中指定的資料庫名DmExampleDB,估計是達夢的資料庫結構和SqlServer有所區別,這個放在後面系統性地再去學習了,至此我們資料庫建立完畢,接下來開始新增針對使用者的CURD操作了。

新增增刪改查操作

我們選中專案中的Controllers目錄,點選右鍵彈出下拉選單依次點選新增->控制器,彈出新增已搭建基架的新項視窗,選擇”檢視使用Entity Framework的MVC控制器“,然後點選”確定“按鈕,如下圖所示:

點選”確定“按鈕後彈出新增檢視的配置視窗,模型類選擇User,資料上下文類選擇DmContext,控制器名稱預設UsersController,然後點選"新增"按鈕。

稍微等待片刻後,我們看到在Controllers目錄中已經生成了UsersController類,開啟這個類檔案,增刪改查的程式碼都已經生成;點開Views檢視目錄,下面新增了Users目錄,在該目錄裡邊增刪改查的檢視也已全部生成。

使用者操作的功能基本都有了,我們稍作改造就可以使用了。首先,我們要在首頁上新增使用者的User的入口選單,以便對使用者進行操作,開啟Views/Shared/_Layout.cshtml,新增如下圖程式碼:

另外,我們在User模型類中新增了建構函式,對新建的User物件的Id和CreateTime,設定了預設值,所以我們在建立的時候就不必要再輸這兩個值了,編輯Views/Users/Create.cshtml,去掉這兩個屬性的程式碼:

編輯Views/Users/Edit.cshtml,將編輯CreateTime的輸入框修改為隱藏型別,編輯的時候不需要輸入了:

最後,我們再修改一下Views/Users/Index.cshtml,在列表頁裡新增ID列,把它顯示出來:

至此我們程式碼修改完畢。

測試執行

完成以上的建立和修改,我們直接在本機上先測試執行一下,頁面效果如下:

首頁上多了一個User選單,我們點選這個選單項後,顯示如下頁面:

這個是使用者列表頁面,因為我們還未新增任何使用者,所以當前列表是空的。我們點選"Create New"連結,跳轉至新增使用者的頁面,來新增一個新使用者試試:

注意:性別是布林型別的,我們輸入truefalse來表示,點選Create按鈕新增使用者,成功後自動跳轉到使用者列表頁面,如下圖所示:

新增完成後,列表頁面上顯示出了一條記錄,為了印證記錄已經插入到sys_user表裡,我們開啟達夢的資料庫管理工具進行檢視:

接下來,我們再測試一下編輯、詳細、刪除操作,也都沒有問題,這裡不再貼圖,到此我們完成了簡單的測試,下一步將專案先發布到本地,然後部署到Web伺服器上。

注意,我們釋出的時候需要修改一下資料庫的連線字串,連線地址要修改為伺服器上的資料庫,然後在程式包管理器控制檯上再次執行update-database命令,主要目的是在伺服器上建立資料庫,當然如果已經建立了就不用去執行這個命令了。然後,依次點選生成->釋出DmExample,彈出釋出配置視窗,釋出目標選擇”資料夾“:

資料夾位置預設即可,然後點選”完成“按鈕

摘要處預設即可,點選"釋出"按鈕,完成釋出操作,系統會將編譯的釋出版本複製到指定的目標位置。

專案部署

專案的部署請參考《國產化之路-安裝WEB伺服器》章節中的”釋出站點“,這裡不再詳細介紹,這裡補充一項,在釋出站點的時候我們需要配置反向代理,ASP.NET Core預設釋出的埠號是5000,所以在配置節中我們設定的埠號對應的也是5000,但當我們的Web伺服器釋出多個站點時,不能使用同一個埠,那麼我們如何去修改ASP.NET Core預設釋出的埠號呢?經查閱資料,我們只需要在appsettings.json的配置檔案裡新增urls配置屬性即可,具體如下:

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*",
  "ConnectionStrings": {
    "DmExample": "Server=localhost;Database=DmExampleDB;User=SYSDBA;Password=dx2263111;"
  },
  "urls": "http://localhost:5005"
}

我們這裡設定的預設埠為5005,然後在Web伺服器裡對該站點的反向代理中的埠號做相應的調整:

# DmExample
location / {
	proxy_pass         http://localhost:5005;
	proxy_http_version 1.1;
	proxy_set_header   Upgrade $http_upgrade;
	proxy_set_header   Connection keep-alive;
	proxy_set_header   Host $host;
	proxy_cache_bypass $http_upgrade;
	proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
	proxy_set_header   X-Forwarded-Proto $scheme;
}

一切準備就緒,在Web伺服器上釋出完成後,開啟站點顯示正常,但是當我們插入一條使用者資料後報錯了。

糾錯

同一個站點,在我們的開發機上測試都沒有問題,然後釋出到統信的作業系統下就出問題,接著又試了一下將資料庫連到Web伺服器,執行環境還是在開發機上試了一下也沒有問題,應該來講大概率就是環境問題了,那環境問題導致哪裡出問題了呢?上面的錯誤資訊,並沒有告訴我們問題出在哪裡,大概意思是講讓我們切換成開發模式可以檢視到更詳細的錯誤資訊,那麼我們切換成開發模式看看,暫停這個站點的守護程式,使用終端進入站點目錄執行下面命令:

# 切換成"Development"模式
export ASPNETCORE_ENVIRONMENT=development 
# 執行站點
dotnet DmExample.dll

然後使用瀏覽器開啟該站點,執行使用者插入操作,頁面顯示資訊變成如下顯示:

反饋的應該是插入的某個欄位資料型別不對,原本輸入的是數字的位置輸入了非數字的字元,導致無法插入造成的,但未給出具體是哪個欄位,分析我們當前的使用者資料型別也就只有年齡是數字型別的,但這個有點不太可能,我們輸入的確實是數字,其它和數字搭邊的就是日期型別了。我們對這兩個欄位做了排查,結果發現是日期型別DateTime的原因,那為什麼會這樣呢?我們做一個簡單的日期型別輸出然後分別在開發機上和Web伺服器上去執行試試看,結果如下:

上圖第一張是在windows開發機上輸出,第二張是在統信UOS上輸出。第一個時間是DateTime.Now輸出,第二個時間是特定時間輸出,主要目的是為區分上下午。很明顯看到,在開發機上是24小時格式的,但統信UOS是12小時格式的,並用中文標識出了上午下午,在插入的時候就現了問題,但看了統信UOS時間設定也是24小時制的,網上找了一下,這個問題並不是只是統信UOS獨有的,在Linux上都有這個問題,找了一下解決辦法,需要在程式開始時設定CultureInfo.DefaultThreadCurrentCulture,我們可以把它加在ProgramMain入口上,程式碼如下:

public static void Main(string[] args)
{
    // 跨平臺 DateTime 中文 上午 下午 解決方案
    CultureInfo.DefaultThreadCurrentCulture = new CultureInfo("zh-CN", true)
    {
	DateTimeFormat = { ShortDatePattern = "yyyy-MM-dd", 
	    FullDateTimePattern = "yyyy-MM-dd HH:mm:ss", LongTimePattern = "HH:mm:ss" }
    };
    CreateHostBuilder(args).Build().Run();
}

CultureInfo.DefaultThreadCurrentCulture屬性用來 獲取或設定當前應用程式域中執行緒的預設區域性,從上面的程式碼理解是,將其設定中文區域,然後指定了短日期、完整時間以及長時間的格式,這裡注意HHhh的區別,HH是24小時制的,而hh是12小時制的。我們在日期輸出小例子里加上這一段程式碼然後再看看其在來個系統統上的輸出是怎麼樣的:

上圖第一張是windows開發機,第二張是統信UOS,我們發現時間格式已經和開發機上格式一致了,然後我們再次釋出站點,進行測試,問題解決。

小結

通過以上的簡單案例,我們實現了在統信UOS作業系統,基於達夢D8資料庫,使用.net core 3.1和EntityFramework core的簡單增、刪、改、查的操作,在這個過程中我們發現windows和Linux類作業系統日期顯示格式的不同對我們所開發的應用造成的影響,這個問題應該並不是統信UOS獨有的問題。我們當前只是個開端,隨著業務的深入,所遇到的問題也將會越來越複雜,具體問題需要具體分析,不管是什麼樣的問題我們相信都有解決辦法。

參考資料

DateTime中文上午下午解決方案:https://blog.csdn.net/i2blue/article/details/105798392

CultureInfo.DefaultThreadCurrentCulture屬性介紹:https://docs.microsoft.com/zh-cn/dotnet/api/system.globalization.cultureinfo.defaultthreadcurrentculture?view=netcore-3.1

在 ASP.NET Core 中使用多個環境:https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/environments?view=aspnetcore-3.1

EF Core連線達夢資料庫參考1:https://blog.csdn.net/lordwish/article/details/104501226

EF Core連線達夢資料庫參考2:https://blog.csdn.net/lordwish/article/details/108532022

相關文章