Postgres database for Silverlog. This repo owns the schema (database-first) — the .NET backend connects to it and scaffolds its models from these tables; it does not generate or own the schema itself.
- Docker + Docker Compose
- dbmate (
brew install dbmate) — the migration tool used to create/update tables psqlversion 17.6+ recommended (optional, for manually inspecting the database). dbmate uses your locally installedpg_dump/psqlto regeneratedb/schema.sql; an older client can produce or fail to load a dump containing\restrict/\unrestrictmeta-commands that only 17.6+ understands.
- Copy
.env.exampleto.envand fill in real values (ask a teammate for shared local dev credentials, or just pick your own — this file is git-ignored and never committed). - Start Postgres:
docker compose up -d
- Apply all migrations (creates the tables):
dbmate up
- (Optional) Load sample/test data.
psqldoesn't read.envitself, so export the variables into your shell first:Safe to re-run any time — it truncates and reloads. All seeded rows use obviously-fake values (e.g.set -a && source .env && set +a psql "$DATABASE_URL" -f db/seed.sql
@example.testemails) so they're never mistaken for real data.
See docs/docker-guide.md for a fuller explanation of the Docker/Postgres setup.
The database is just standard Postgres reachable over TCP — nothing .NET-specific is required on this side. From the backend repo:
- Add the Npgsql EF Core provider:
dotnet add package Npgsql.EntityFrameworkCore.PostgreSQL dotnet add package Microsoft.EntityFrameworkCore.Design
- Connection string shape (values come from this repo's
.env— get the actual password from whoever set up your local.env, don't hardcode it):Host=localhost;Port=5432;Database=silverlog;Username=silverlog;Password=<your local password> - Scaffold C# models from the existing tables (database-first):
Re-run this command whenever the schema changes here, to regenerate the models.
dotnet ef dbcontext scaffold "Host=localhost;Port=5432;Database=silverlog;Username=silverlog;Password=<your local password>" Npgsql.EntityFrameworkCore.PostgreSQL -o Models --context SilverlogDbContext
users.role is a native Postgres ENUM type (user_role, values admin/student),
not a plain text column. Npgsql needs this mapped explicitly or scaffolding/queries
against it will fail. Before scaffolding, register the enum mapping:
var dataSourceBuilder = new NpgsqlDataSourceBuilder(connectionString);
dataSourceBuilder.MapEnum<UserRole>("user_role");
var dataSource = dataSourceBuilder.Build();where UserRole is a C# enum with members matching the Postgres labels
(Admin, Student) — Npgsql matches them case-insensitively by default.
This section is a hand-maintained summary for quick reference. The definitive, always-current schema is
db/schema.sql(auto-regenerated by dbmate on every migration) — if this section and that file ever disagree, trustdb/schema.sql.
users
user_id (PK, bigint identity)
email (text, not null; unique case-insensitively via index on lower(email))
name (text, not null)
role (user_role enum: 'admin' | 'student', not null, default 'student')
entries
entry_id (PK, bigint identity)
user_id (FK -> users.user_id, ON DELETE CASCADE, indexed)
entry_text (text, not null)
entry_date (timestamptz, not null, default now())
codes
code_id (PK, bigint identity)
wem_code (text, unique, not null)
wem_description (text, not null)
activities
activity_id (PK, bigint identity)
entry_id (FK -> entries.entry_id, ON DELETE CASCADE)
code_id (FK -> codes.code_id, ON DELETE RESTRICT, indexed)
unique (entry_id, code_id) -- also serves as the index for entry_id lookups
Relationships:
users ──(cascade)──< entries ──(cascade)──< activities >──(restrict)── codes
- Deleting a user deletes all their entries (and, transitively, those entries' activities).
- Deleting a code is blocked while any activity still references it.
This repo is the source of truth for the schema. To change it:
dbmate new <descriptive_migration_name>
# edit the generated file in db/migrations/, then:
dbmate upNever hand-edit db/schema.sql — it's auto-regenerated by dbmate on every migration.
Commit both the new migration file and the updated schema.sql.