廣告
EF Core 實戰指引:使用 dotnet-ef 建立 PostgreSQL DbContext - 當 .NET Core 要使用 EF Core 去存取 PostgreSQL 時,可以先使用 dotnet-ef 的工具,協助產生對應 PostgreSQL schema 的 DBContext

EF Core 實戰指引:使用 dotnet-ef 建立 PostgreSQL DbContext

Last updated on

若是有使用過 Entity Framework, EF 的經驗,必然對 DBContext 類別有所了解。在 EF 時可以使用 Visual Studo 的 UI 工具,以 Database-First 的方式建立 DBContext。

本篇文章則是記錄 Database-First 的開發方式下,EF Core 如何使用 CLI 來產生 DBContext。

🔖 長話短說 🔖

ℹ️ 系列導讀:本文屬於「EF Core 實戰系列」,完整系統性教學請參見 EF Core 實戰系列從指令到進階應用總整理

  • EF Core 要操作 PostgreSQL 的話,可使用 Npgsql.EntityFrameworkCore.PostgreSQL
  • 可使用 dotnet tool update --global dotnet-ef 進行 dotnet-ef 版本更新
  • 可使用 dotnet ef dbcontext scaffold 的指令,協助從資料庫已存在的 Schema 產生對應的 dbcontext。
  • 若專案內未參考 Microsoft.EntityFrameworkCore.Design 的話,dotnet ef dbcontext scaffold 無法順利動作。
  • 機敏性資料,可使用 user-secrets 工具。

操作環境:

  • Windows 11
  • .NET Core 7
  • Postgresql 15.1

前置作業

建立 PostgreSQL

選擇使用 Docker compose 的方式,來建立 PostgreSQL。

使用下面的 yml 設定,預設儲存為 docker-compose.yml 檔。當然也可以存為其他更具識別性的名稱。

version: '3.6'

services:

  postgres:
    image: postgres:15.1
    restart: always
    environment:
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=psg1234
    ports:
      - "5432:5432"
    volumes:
      - postgres-data:/var/lib/postgresql/data

volumes:
  postgres-data:

若是存為 docker-compose.yml 時,直接執行下述語法即可。

docker-compose up -d

若是存為其他檔名時,需要使用 -f 指定 yml 的檔案。

docker-compose -f <docker-compose.yml> up -d

接著建立一個簡單的表格。

create table todo
(
    id    integer generated always as identity,
    title varchar(30)                         not null,
    date  timestamp default current_timestamp not null
)

建立 .NET Core Lab 專案

# 建立新的 console 專案
dotnet new webapi -n efcore_lab

cd efcore_lab

# 安裝 Nuget 套件
dotnet add package Npgsql.EntityFrameworkCore.PostgreSQL --version 7.0.1
dotnet add package Microsoft.EntityFrameworkCore.Design

Npgsql.EntityFrameworkCore.PostgreSQL 是 postgreSQL 的 DB Provider。

若是沒有安裝 Microsoft.EntityFrameworkCore.Design,後續執行 dotnet ef dbcontext scaffold ... 的指令時,會出現錯誤提示。

未安裝 Microsoft.EntityFrameworkCore.Design 的錯誤提示
未安裝 Microsoft.EntityFrameworkCore.Design 的錯誤提示

Entity Framework Core Tools

若您尚未安裝 EF Core 的全域工具 (dotnet-ef),或是不熟悉如何更新工具版本,請先參考 EF Core CLI Tool 操作筆記 進行環境設置。

產生 DBContext

接著,就要運用 dotnet ef dbcontext scaffold 的指令,來協作我們產生對應資料庫的 DBContext 了。

dotnet ef dbcontext scaffold <connection_string> Npgsql.EntityFrameworkCore.PostgreSQL

# 例子
dotnet ef dbcontext scaffold "Host=localhost;Database=postgres;Username=postgres;Password=psg1234;Trust Server Certificate=true" Npgsql.EntityFrameworkCore.PostgreSQL
順利更新 DBContext
順利更新 DBContext

若是想要指定產生出來的 <DBContext.cs> 放到指定位置,記得額加使用 -o <Path> 的指令。否則產生出來的位置與 .csproj 的位置相同。

# 指定 DBContext 輸出位置為 Models 資料夾
dotnet ef dbcontext scaffold <connection_string> Npgsql.EntityFrameworkCore.PostgreSQL -o Models

異常排除

狀況一、資料庫不存在

若是連線字串內的 Database 名稱與實際資料庫名稱大小寫不同,會發生找不到資料庫的錯誤。要特別注意。

資料庫名稱大小寫不同,回應資料庫不存在
資料庫名稱大小寫不同,回應資料庫不存在

狀況二、已存在檔案

若先前已經有產生過 <DBContext> 相關檔案,直接執行指令會出現 The following file(s) already exist in directory 'c:\Codes\lab\efcore_lab\': PostgresContext.cs,Todo.cs. Use the Force flag to overwrite these files. 錯誤訊息。

已存在資料,需指定覆寫原有資料
已存在資料,需指定覆寫原有資料

所以必須在指令加上 -f,告知 ef dbcontext scaffold 要覆寫先前已存在的檔案。

dotnet ef dbcontext scaffold <connection_string> Npgsql.EntityFrameworkCore.PostgreSQL -o Models -f

但要注意的是,上述的指令所產生出來 DBContext.cs 內,會含有連線字串,為了避免資訊外洩,務必記得移除,改用 configuration 注入的方式。

dotnet ef 產生出來的 PostgresContext 內容
dotnet ef 產生出來的 PostgresContext 內容

user-secrets

也可以使用 user-secrets 的方式,來管理機敏資料,避免連線字串直接記錄在程式碼之中。

# 待調整為 Postgresql 的方式
dotnet user-secrets init
dotnet user-secrets set ConnectionStrings:lab <connection_string>
dotnet ef dbcontext scaffold Name=ConnectionStrings:lab Npgsql.EntityFrameworkCore.PostgreSQL

user-serets init 初始化之後,會產生一組 UserSecretsId,並存在 .csproj 之中。

user-secrets init
user-secrets init
csproj 專案檔內的 UserSecretsId
csproj 專案檔內的 UserSecretsId

使用 user-secrets set 後,系統會把機敏資料存放到 C:\Users\<user>\AppData\Roaming\Microsoft\UserSecrets\<UserSecretsId>\secrets.json 之中。

使用 user-secrets 設定連線字串
使用 user-secrets 設定連線字串
secrets.json 內的資料
secrets.json 內的資料

最後使用 dotnet ef dbcontext scaffold 使用 user-secrets 內的連線字串來產生 DBContext。可以發現連線字串不會被記錄在 DBContext 之中。

使用 user-secrets 內的連線字串
使用 user-secrets 內的連線字串
使用 user-secrets 產生出來的 PostgresContext
使用 user-secrets 產生出來的 PostgresContext

延伸閱讀

▶ 站內文章

▶ 站外文章


💬 參與討論 你現在開發 EF Core 時,是習慣先寫 Code (Code-First) 還是先建 Database (Database-First) 呢?這兩種流派各有擁護者,歡迎在底下留言分享你的看法與實戰經驗!

💬 留下你的想法

有問題、不同看法,或是你踩過類似的坑?歡迎留言討論,我會盡量回覆。