Chuyển tới nội dung chính

Migration: MSSQL → PostgreSQL

Mục tiêu: đồng nhất cơ sở dữ liệu về PostgreSQL. Cách tiếp cận chưa chốt — Dev sẽ review 3 hướng: sửa trực tiếp / lớp cấu hình / tách source khác. Trang này cung cấp số liệu để ra quyết định đó.

Phạm vi đo được (từ source thật)

Hạng mụcGiá trịGhi chú
Số DB vật lý1 (SOEZY_DESEARCHDB_DEV)"SoEzyEntities" và "SOEZY_REPORT_DB" là tên context, không phải 2 DB
Stack data-access2 khác nhauWorker: EF6 EDMX (database-first). API: EF Core 5 code-first scaffold
EDMXSoEzyEntities.edmx 161KB / 2123 dòngProvider System.Data.SqlClient, token SQL2012, nhúng làm build resource
Raw SQL trong source2 call siteCả hai trong SystemExceptionSendWarningEmailEngine.cs
Stored procedure3 (JSON-in/JSON-out)Body nằm trong DB, không có trong repo
Script DDL tay4 file .sqlChỉ phủ 4 bảng mới nhất
Số entity/bảng~25–28 (worker EDMX) / 26 DbSet (API)API là tập khác/giao, không trùng khít
Migration code-managed?KhôngKhông có thư mục EF Migrations; schema sống trong DB thật

Hai stack — hai cách migrate

Worker (DE_Searches)API (DE_Searches_API_NetCore)
ORMEF6 EDMX database-firstEF Core 5 code-first scaffold (UseSqlServer)
Frameworknet4.5.2net5.0
Provider PostgresKhông có EF6 Npgsql production trên net4.x → buộc re-platform sang EF Core/NpgsqlNpgsql.EntityFrameworkCore.PostgreSQL (đổi UseSqlServerUseNpgsql)
Độ khóCao (kèm retarget framework)Trung bình (nhưng vướng DLL Ezy.*)

3 hướng tiếp cận để Dev review

Hướng A — Sửa trực tiếp (in-place)

Đổi provider tại chỗ: API UseSqlServerUseNpgsql; worker bỏ EDMX, scaffold lại từ Postgres.

  • Ưu: ít kiến trúc mới, một codebase.
  • Nhược: đụng ngay DLL Ezy.*.MSSQL (không recompile được); worker phải retarget net8 + bỏ EDMX cùng lúc → rủi ro cao.

Hướng B — Lớp cấu hình (provider abstraction + flag)

Trừu tượng hoá provider, chọn MSSQL/Postgres qua config; chạy song song để so sánh.

  • Ưu: rollback dễ, migrate dần từng bảng/từng context.
  • Nhược: EF6 EDMX rất khó nhét sau abstraction; vẫn kẹt DLL Ezy.*.

Hướng C — Tách source khác (data-access service mới)

Viết lớp data-access mới trên EF Core/Npgsql (.NET 8), cả worker lẫn API gọi qua đó, loại dần DLL Ezy.*.

  • Ưu: thoát hẳn binary MSSQL closed-source; thống nhất 1 stack.
  • Nhược: công lớn nhất; phải dựng lại repository/bulk/stored-proc layer.

Gợi ý: nếu DLL Ezy.* không có bản Postgres từ vendor thì Hướng C gần như bắt buộc cho phần worker, vì A/B đều không vượt được binary MSSQL.

Đầu việc lớn (epics)

EPIC 0 — Quyết định & chuẩn bị

  • Liên hệ vendor: có bản Postgres của Ezy.Module.BaseMSSQLData / MSSQLRepository / EzyEFStoreRepository không? Verify: câu trả lời rõ ràng có/không (chốt được hướng A/B vs C).
  • Trích full schema từ DB thật (không chỉ 4 script DDL). Verify: dump đầy đủ ~25+ bảng.
  • Chốt cách map ROWVERSION (xmin vs trigger). Verify: POC 1 bảng có concurrency token chạy được trên Postgres.

EPIC 1 — Schema → PostgreSQL

  • Chuyển DDL: IDENTITY(1,1)GENERATED AS IDENTITY, NVARCHAR(MAX)text, datetimetimestamp, [dbo].[x]→identifier thường, ROWVERSION→giải pháp đã chốt. Verify: tạo schema rỗng chạy được trên Postgres.
  • Viết 3 stored proc JSON-in/JSON-out lại dạng function Postgres (hoặc chuyển vào app code). Verify: so output JSON với proc MSSQL cũ.

EPIC 2 — API (.NET 5, dễ hơn)

  • Thêm Npgsql.EntityFrameworkCore.PostgreSQL, đổi UseSqlServerUseNpgsql. Verify: API CRUD chạy trên Postgres.
  • Xử lý Z.EntityFramework.Extensions (bulk) — cần build/giấy phép hỗ trợ Postgres. Verify: bulk insert chạy.
  • Thay System.Data.SqlClient ở các raw call → Npgsql. Verify: 2 call site engine email chạy.

EPIC 3 — Worker (.NET Framework, khó nhất)

  • Re-platform data layer EF6 EDMX → EF Core/Npgsql (phụ thuộc EPIC retarget bên Playwright). Verify: 1 worker đọc/ghi TextSearch_* trên Postgres.
  • Thay/loại các DLL Ezy.*.MSSQL theo hướng đã chốt. Verify: không còn ref binary MSSQL.

EPIC 4 — Dữ liệu & cutover

  • Công cụ chuyển data MSSQL→Postgres (pgloader / script). Verify: đếm dòng + checksum khớp.
  • Test song song (dual-write hoặc so đọc). Verify: kết quả khớp giữa 2 DB.

3 thứ khó nhất (đã xác nhận từ source)

  1. ROWVERSION/TimeStamp concurrency token trên MỌI bảng — Postgres không có tương đương; phải remap sang xmin hoặc cột trigger trên ~50 bảng và test lại toàn bộ hành vi concurrency của EF.
  2. EF6 EDMX gắn chặt SqlClient SSDL — không có EF6 Npgsql production trên net4.5.2; thực tế phải re-platform toàn bộ worker data layer sang EF Core/Npgsql (kéo theo việc port .NET Framework → .NET hiện đại).
  3. DLL Ezy.*.MSSQL closed-source — connection, bulk-ops, stored-proc nhúng trong binary không recompile được; cần bản Postgres từ vendor hoặc viết lớp thay thế; 3 stored proc (không có trong repo) phải viết lại.

Rủi ro & lưu ý

  • Credential DB plaintext ở 3+ nơi (Core/App.config, App_Data/Setting.txt, hardcode trong Categories.SOEZY_DESEARCHDB_DEVModel.cs) → xử lý cùng lúc khi đổi connection string.
  • Connection string stored-proc lại nằm trong một bảng DB (ConfigStoreProcedure4Reports) → đừng bỏ sót.
  • Schema phần lớn chỉ tồn tại trong DB thật, không trong repo → phải dump trước khi làm gì.
  • API DbSet và worker EDMX là tập khác nhau → migrate phải gộp/đối chiếu, không copy 1-1.