Skip to content

feat(db): Add EF Core code-first migrations and PostgreSQL support - #77

Open
tintinhamans wants to merge 7 commits into
GeneralsOnlineDevelopmentTeam:mainfrom
tintinhamans:arctic/feat/ef-migrations-postgres
Open

tintinhamans wants to merge 7 commits into
GeneralsOnlineDevelopmentTeam:mainfrom
tintinhamans:arctic/feat/ef-migrations-postgres

Conversation

@tintinhamans

@tintinhamans tintinhamans commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor

Replaces the hand-written Database_Structure SQL with EF Core code-first migrations and adds PostgreSQL next to MySQL. Database:db_provider picks mysql (default, deprecated, will be dropped in next major) or postgres. Each provider has its own context and InitialCreate; the MySQL one matches the prod schema exactly, including the website tables, and adds the missing idx_finished_time index. Postgres uses timestamptz, jsonb and partial indexes. All timestamps are UTC on both, and the token-state upsert is plain EF now, so there's no raw SQL left.

The server never migrates on its own and refuses to start while migrations are pending. GenOnlineService migrate applies them (asks first, --yes for deploys). --baseline marks an existing database as InitialCreate after checking every table, column and index is already there. Verified on Postgres 17 and MariaDB 12.1, including baseline against a copy of the prod schema.

Before deploying, run this once on prod and test, otherwise the service won't start:

GenOnlineService migrate --baseline

After that, migrate --yes runs as a deploy step before starting the new version.

Builds on #78, so its commits stay in the diff until it lands. The last commit adds the Npgsql meter and trace source and strips the Npgsql data source name from spans.

Replace the hand-written schema in Database_Structure/ with EF Core
migrations and add PostgreSQL as a second database provider next to
MySQL/MariaDB. Both run on EF Core 10 (Npgsql and the Microting fork of
Pomelo, since Pomelo has no EF Core 10 release).

- Select the provider with Database:db_provider ("mysql", the default, or
  "postgres"); MySQL/MariaDB support is deprecated and will be removed in
  the next major version
- Keep one provider-neutral model with per-provider contexts and migration
  sets; the MySQL InitialCreate mirrors the production schema, the
  PostgreSQL model stores unsigned values as signed, JSON as jsonb and
  timestamps as timestamptz; all timestamps are normalized to UTC
- Model every index production relies on (match feed, social lookups, ban
  reconciliation, device/IP lookups) plus the schema the website shares
  (web_sessions, users.google_id/google_email/permissionslevel); use
  partial indexes on PostgreSQL for the pending-publication and banned-user
  lookups
- Add "GenOnlineService migrate [--yes] [--baseline]" as the only way to
  change the schema; it lists pending migrations, prompts interactively and
  fails fast without a TTY unless --yes is passed
- Add --baseline to adopt an existing pre-migrations database: it verifies
  every table, column (incl. nullability) and index InitialCreate expects
  and records InitialCreate without touching data
- Refuse to start the server while migrations are pending, with a baseline
  hint for existing installs
- Replace the raw ON DUPLICATE KEY token upsert with EF calls and set match
  start/finish times in code instead of SQL column defaults
- Detect duplicate keys on both providers (MySQL 1062, PostgreSQL 23505)
- Add a local dotnet-ef tool manifest and update the README for setup,
  upgrading existing installs and per-provider schema changes
Collect Npgsql spans and metrics next to MySqlConnector's, strip the
connection-derived Npgsql data source name from database spans, and
keep Npgsql logging at Warning like MySqlConnector.
@tintinhamans
tintinhamans force-pushed the arctic/feat/ef-migrations-postgres branch from dabd3b4 to e6969c1 Compare October 29, 2026 05:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant