(16/30)大家一起學Blazor:建立資料庫

(16/30)大家一起學Blazor:建立資料庫

我們現在有了基本的日誌,但是每次輸入完重新載入頁面資料都會重置,因為這些資料都只存在於瀏覽器,沒有真正儲存到資料庫,為了保存下來,我們要跟資料庫連接。

最後更新 2021/12/18 下午11:34
StrayaWorker
預計閱讀 5 分鐘
分類
Blazor
專題
一起學Blazor系列
標籤
.NET C# ASP.NET Core Blazor

我們現在有了基本的日誌,但是每次輸入完重新載入頁面數據都會重置,因為這些數據都只存在於瀏覽器,沒有真正儲存到資料庫,為了保存下來,我們要跟資料庫連接。
(註:Blazor WebAssembly 沒有直接跟資料庫互動的能力,不過微軟有提供ASP.NET Core hosted 選項,可以在建立 Blazor WebAssembly 時一併建立 ASP.NET Core Web API 專案)

Entity Framework Core

首先在appsettings.json加入連線字串,因為測試用,所以 SqlServer 用本地資料庫。

{
  "ConnectionStrings": {
    "DBConnection": "Server=(localdb)\\MSSQLLocalDB;database=Blog;integrated security=true;"
  },
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*"
}

接著 NuGet 下載兩個元件,分別為Microsoft.EntityFrameworkCore.SqlServerMicrosoft.EntityFrameworkCore.Tools,這兩個元件是跟 SqlServer 互動用的 ORM 元件,ORM 又是什麼呢?

專案工程組態檔:BlazorServer.csproj

<Project Sdk="Microsoft.NET.Sdk.Web">

	<PropertyGroup>
		<TargetFramework>net6.0</TargetFramework>
		<Nullable>enable</Nullable>
		<ImplicitUsings>enable</ImplicitUsings>
	</PropertyGroup>

	<ItemGroup>
	  <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="6.0.1" />
	  <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="6.0.1">
	    <PrivateAssets>all</PrivateAssets>
	    <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
	  </PackageReference>
	</ItemGroup>

</Project>

遠古時代的程式開發者想從SqlServer 取資料回來,都必須學習SQL 語句,後來.NET 平台(包括VBC#)開發了ADO.NET 這個取資料的好工具,將資料取回來後一一跟程式mapping,但ADO.NET 在資料映射上不如人意,微軟便推出了Entity Framework,這就是初始的ORM(Object-Relational Mapper),讓開發者可以把資料變成實體(entity),不用實際去接觸SQL 語句,且有了設計工具(Designer) 讓程式開發者更好操作。

但也有些人覺得Entity Framework 太笨重就轉向另一個輕便的工具Dapper的懷抱,筆者也用過Dapper,如果是喜歡自己組SQL 語句的人確實會覺得方便。

.NET Core 這個跨平台版本的ORM 就是用Entity Framework Core 去做資料映射的處理。

安裝完元件後,新增一個類別 AppDbContext,繼承DbContext,裡面的建構函式將DbContextOptions<AppDbContext> options傳給基底類別 也就是DbContext

AppDbContext.cs

using Microsoft.EntityFrameworkCore;

namespace BlazorServer.Models;

public class AppDbContext : DbContext
{
	public AppDbContext(DbContextOptions<AppDbContext> options) : base(options)
	{
	}

	public DbSet<BlogModel>? Blogs { get; set; }

	public DbSet<PostModel>? Posts { get; set; }
}

接著打開Program.cs,註冊使用資料庫,這邊用的是UseSqlServer(),當然也有UseMysql()UseOracle()可以用,只要安裝對應的元件即可。

打開套件管理器主控台,輸入命令Add-Migration Init,告訴Entity Framework Core 要建立一個資料庫遷移,接著就會產生遷移目錄Migration,這是Entity Framework Core 的特點,在程式跟資料庫之間產生中介Migration,另外Migration 一大好處就是在真正確定前,都可以不斷修改,等確定後再更新資料庫。

Relation between Blog and Post

接下來要在Post 裡面加上BlogIdBlog 對於Post 而言是主表之於子表,如果新增遷移的時候沒有加入對主表的關聯(也就是主表外鍵關聯子表),EF Core 很聰明會主動加上,但欄位名就會是Model+Key 的名稱,變成BlogModelBlogId,我們來把名稱簡化。

先在PostModel加上兩個屬性,BlogIdBlog,切記一定要這樣添加,BlogId是存在資料庫用的,Blog則是在關聯資料的時候有個實體可以用,讓我們不用自己 join 資料表,後續會再說明。

接著用Remove-Migration將原先的 Migration 清除,再新增一次 Migration,即執行命令Add-Migration Init,可以看到新的 Migration 有簡化的名稱BlogId了,這時候再去更新資料庫。

使用命令Update-Database去更新資料庫,然後打開SQL Server 物件總管,可以找到剛才建立的資料庫Blog,資料庫名來自連線字串database的名稱,可以看到資料庫已經建起來了,過程中沒有用到 SQL 語句或是 SSMS 介面。

不過有一點要特別注意,中途如果換資料庫的話,原先的 Migration 有很大機率產生問題,各家資料庫的資料型別都有差異,所以最好一開始就規劃好用哪個資料庫。

除了AddDbContext<T>這種最常見的做法,還有AddDbContextFactory<T>這種在個別元件產生新的DbContext的方法,因為AddDbContext<T>的生命週期是scoped,對 Blazor Server 來說也就是除非關閉系統,否則DbContext都不會 dispose,有些人希望生命週期僅限於元件即可,就可以用AddDbContextFactory<T>

參考:

  1. Entity Framework
  2. Dapper
  3. Database Providers
  4. New DbContext instances

註:本文程式碼透過 .NET 6 + Visual Studio 2022 重構,可點擊原文連結與重構後程式碼比較學習,謝謝閱讀,支援原作者

繼續探索

延伸閱讀

更多文章
同分類 / 同標籤 2021/12/25

(29/30)大家一起學Blazor:Blazor單元測試

開發一個系統最無聊的過程大概就是解決 Bug 了,尤其是那種嘗試對 null 物件取值的錯誤(`Object reference not set to an instance of an object.`),這應該是大部分人剛踏入程式設計領域最常碰到的問題,為了從枯燥的解決 Bug 過程解脫,這篇就來介紹`單元測試`。

繼續閱讀
同分類 / 同標籤 2021/12/25

(28/30)大家一起學Blazor:Policy-based authorization

之前有說到`ASP.NET Core Identity` 使用的是基於`Claim` 的驗證,其實`ASP.NET Core Identity` 有不同類型的授權方式,最簡單的`登入授權`、`角色授權`、`Claim 授權`,但上述幾種都是以一種方式實現:原則授權(`Policy-based authorization`)。

繼續閱讀