以前我以為.Net只能在Windows下開發,而且必須搭配微軟提供的周邊產品(SQLServer等)使用,感覺就是個開發成本很高的組合,因此一直以來我自己對.Net是沒什麼興趣的。

直到最近研究才發現.Net近幾年已經開源免費,且支援跨平台,可以在Linux上運行,也能搭配各種資料庫(MySQL等)使用,如此一來開發成本就大大降低。

我還發現Asp.Net Core在開發Web API上非常方便,跟Spring Boot/MVC有異曲同工之妙,只要在Controller中的方法上加上[HttpGet]特性就可以實現Http的Get請求,同時也自帶DI容器可以自動管理物件之間的依賴,對我這種非常喜愛DI的人來說是大大加分。

有著以上優點加上我自己本來就寫了幾年的C#,所以我決定要來好好學習.Net Web開發。

而在做Web開發時最重要的環節之一就是存取資料庫,通常會使用ORM框架來幫助我們完成這個工作,而微軟也提供一套官方的ORM框架就是Entity Framework Core(EFCore),不過大多數的文檔跟教學都是教EFCore連SQLServer,連接MySQL的參考資料就比較少。

因此這篇文章就來記錄如何在.Net 6中使用EFCore連線MySQL。

開新的Web API專案

這邊我使用的IDE是Rider,首先先開一個.Net 6的Web API專案,取名叫EFCoreMySQL。

安裝EFCore

再來是要安裝EFCore相關套件,首先在Rider中對專案按右鍵開啟NuGet管理介面。

接著搜尋並安裝以下套件

  • Microsoft.EntityFrameworkCore // EFCore本體,這裡我安裝的是7.0.2版
  • Microsoft.EntityFrameworkCore.Tools // 可以輸入一些EFCore指令的套件,這裡我安裝的是7.0.2版
  • Pomelo.EntityFrameworkCore.MySql // 驅動EFCore與MySQL連線的套件,這裡我安裝的是7.0.0版

安裝完後可以看到

準備MySQL資料庫

這裡我使用的是MySQL 8,打開後,簡單的建立一個資料庫叫efcoremysql。

1
2
create database efcoremysql;
use efcoremysql;

因為EFCore支持我們在C#中定義好資料模型後,直接幫我們反向寫回資料庫的表中,因此這裡我們就不用建資料表,等等再從EFCore生成即可。
此時我們資料庫中是沒有表的。

1
show tables;

輸入上面指令後會看到

1
Empty set (0.02 sec)

建立資料模型

現在就可以來建立我們要儲存的資料模型了,假設需求是要儲存用戶的資料,這裡就可以在專案資料夾下新增一個資料夾叫Models,然後新增一個User.cs。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace EFCoreMySQL.Models;

[Table("User")]
public class User
{
[Key]
public int Id { get; set; }

public string? Name { get; set; }
public string? Password { get; set; }
public DateTime CreatedAt { get; set; }
}

建立DbContext物件

接著在專案資料夾下再新增一個Database資料夾,並新增ApplicationDbContext.cs,作為操作資料庫的物件。

1
2
3
4
5
6
7
8
9
10
11
12
13
using EFCoreMySQL.Models;
using Microsoft.EntityFrameworkCore;

namespace EFCoreMySQL.Database;

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

public DbSet<User> Users { get; set; }
}

然後到appsettings.json中設定登入MySQL的必要資訊(主機位置, 要連哪個資料庫, 帳號密碼等…)。
這裡我的MySQL帳密都是root,database是剛剛建立好的efcoremysql,主機位置則是localhost。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
// --- 加入以下資訊 ---
"ConnectionStrings": {
"DefaultConnection": "server=localhost; database=efcoremysql; user=root; password=root"
}
// --- 加入以上資訊 ---
}

將ApplicationDbContext配置到DI容器中

回到Program.cs,在var app = builder.Build();之前加入

1
2
3
4
5
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
builder.Services.AddDbContext<ApplicationDbContext>(options =>
{
options.UseMySql(connectionString, ServerVersion.AutoDetect(connectionString));
});

到這裡,我們就成功的設定好DbContext囉,接下來就是要來根據User物件在MySQL生成對應的User資料表。

Migration

EFCore的Migration功能就是用來生成資料表使用的,它除了可以幫我們在最一開始建立表之外,在往後開發如果資料模型有變更,甚至是更換資料庫等,讓我們只需要下簡單的幾個指令,就可以幫我們保持C#中的資料模型與資料庫中的資料表同步。

要下dotnet-ef的指令,首先要先安裝

1
dotnet tool install --global dotnet-ef

安裝完後,就可以開啟cmd cd到專案路徑,接著

1
dotnet ef migrations add InitialCreate

這樣就建立一個Migration了,然後要更新到資料庫

1
dotnet ef database update

下完這兩個指令後,再回到MySQL中show tables;,就可以看到user資料表了。

測試

最後來測試一下,在Controllers資料夾中新增UserController.cs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
using EFCoreMySQL.Database;
using EFCoreMySQL.Models;
using Microsoft.AspNetCore.Mvc;

namespace EFCoreMySQL.Controllers;

[ApiController]
public class UserController : ControllerBase
{
private ApplicationDbContext _applicationDbContext;

public UserController(ApplicationDbContext applicationDbContext)
{
_applicationDbContext = applicationDbContext;
}

[HttpGet]
[Route("/Add")]
public ActionResult<string> Add(string name)
{
_applicationDbContext.Add(new User() { Name = name });
_applicationDbContext.SaveChanges();

return Ok("Add Success!");
}
}

接著執行/Add並傳入的名字,就會看到成功新增資料到MySQL中囉!

參考資料

MySQL Database with .NET Core 6 and Entity Framework
ChatGPT

__END__