Skip to content

feat(data): replace pre-seeded db with EF Core migrations and HasData() (#459)#460

Merged
nanotaboada merged 4 commits intomasterfrom
feat/ef-core-migrate-async-at-startup
Apr 9, 2026
Merged

feat(data): replace pre-seeded db with EF Core migrations and HasData() (#459)#460
nanotaboada merged 4 commits intomasterfrom
feat/ef-core-migrate-async-at-startup

Conversation

@nanotaboada
Copy link
Copy Markdown
Owner

@nanotaboada nanotaboada commented Apr 9, 2026

Summary

  • Replaces the committed storage/players-sqlite3.db binary blob with db.Database.MigrateAsync() at startup — schema and seed data are applied automatically before the first request is served
  • Recreates EF Core migrations using HasData() in OnModelCreating: three self-contained migrations (InitialCreate DDL, SeedStarting11 DML, SeedSubstitutes DML) generated by EF Core with literal InsertData values — no migration calls application methods; NormalizePlayerDataset eliminated
  • Replaces DatabaseFakes.CreateTable() (placeholder schema) and Seed() (bypassed migrations) with MigrateAsync() on in-memory SQLite
  • Suppresses EF Core SQL command logging in production via Serilog override; kept at Information in development
  • Updates entrypoint.sh to report database presence before launch (matching Rust repo style)

Test plan

  • dotnet build --configuration Release passes
  • dotnet test --settings .runsettings — 41/41 pass
  • dotnet csharpier --check . passes
  • docker compose down -v && docker compose up — first run logs "No existing database file found", app starts and serves all 25 players; no raw SQL in container output
  • docker compose down && docker compose up — subsequent run logs "Existing database file found", app starts cleanly

References

Closes #459

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Database location is now configurable via the STORAGE_PATH environment variable.
  • Improvements

    • Database automatically initializes and seeds data on application startup.
    • Simplified database reset—remove the storage volume and restart the application.

…() (#459)

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 9, 2026

Warning

Rate limit exceeded

@nanotaboada has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 14 minutes and 35 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 14 minutes and 35 seconds.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 2916ec0a-b8c9-48f3-8aca-0ca5bb410004

📥 Commits

Reviewing files that changed from the base of the PR and between 68d3f0d and 55be5e6.

📒 Files selected for processing (3)
  • .sonarcloud.properties
  • adr/0003-use-sqlite-for-data-storage.md
  • src/Dotnet.Samples.AspNetCore.WebApi/Extensions/ServiceCollectionExtensions.cs

Walkthrough

This PR replaces a pre-seeded SQLite database file committed to the repository with EF Core runtime migrations applied during application startup via MigrateAsync(). Seed data is now configured in OnModelCreating using HasData() rather than stored in a binary blob, eliminating manual migration scripts and Docker copy steps.

Changes

Cohort / File(s) Summary
Documentation & Architectural Records
.github/copilot-instructions.md, CHANGELOG.md, README.md, adr/0003-use-sqlite-for-data-storage.md
Updated documentation to reflect migration from committed database file to runtime EF Core migrations; removed references to run-migrations-and-copy-database.sh script and pre-seeded DB file; noted automatic migration execution at startup.
Application Startup & Configuration
src/Dotnet.Samples.AspNetCore.WebApi/Program.cs, src/Dotnet.Samples.AspNetCore.WebApi/Extensions/ServiceCollectionExtensions.cs, src/Dotnet.Samples.AspNetCore.WebApi/appsettings.json, src/Dotnet.Samples.AspNetCore.WebApi/appsettings.Development.json
Added MigrateAsync() call in Program startup; made SQLite database path configurable via STORAGE_PATH environment variable with automatic directory creation; updated Serilog logging to include EF Core database command tracing.
Data Seeding & Entity Configuration
src/Dotnet.Samples.AspNetCore.WebApi/Data/PlayerDbContext.cs, src/Dotnet.Samples.AspNetCore.WebApi/Dotnet.Samples.AspNetCore.WebApi.csproj
Added HasData() calls in OnModelCreating to seed 25 players via PlayerData methods; removed .csproj content item that bundled pre-seeded database file.
Docker & Runtime Infrastructure
Dockerfile, scripts/entrypoint.sh, scripts/run-migrations-and-copy-database.sh
Removed Dockerfile steps copying pre-seeded database file; simplified entrypoint script to remove bundled DB fallback logic; deleted migration copy script entirely.
Project Configuration
.gitignore
Added pattern storage/*.db to prevent committing database files.
Test Utilities
test/Dotnet.Samples.AspNetCore.WebApi.Tests/Utilities/DatabaseFakes.cs
Replaced CreateTable() and Seed() helper methods with MigrateAsync() to apply full EF Core migration chain on in-memory test database.

Sequence Diagram(s)

sequenceDiagram
    participant Startup as Application Startup
    participant DI as Dependency Injection
    participant EFCore as EF Core
    participant SQLite as SQLite Database

    Startup->>DI: CreateAsyncScope()
    DI->>EFCore: Resolve PlayerDbContext
    EFCore->>SQLite: Connect to players-sqlite3.db
    Startup->>EFCore: Database.MigrateAsync()
    EFCore->>SQLite: Apply InitialCreate migration (DDL)
    EFCore->>SQLite: Apply SeedStarting11 migration (DML)
    EFCore->>SQLite: Apply SeedSubstitutes migration (DML)
    SQLite-->>EFCore: Schema + 25 seed records created
    EFCore-->>Startup: Migration complete
    Startup->>Startup: Register middleware & endpoints
    Startup->>Startup: RunAsync()
    Note over Startup,SQLite: App ready to serve 25 players
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Assessment against linked issues

Objective Addressed Explanation
Wire MigrateAsync() at startup and remove pre-seeded database file [#459 Part 1]
Update .gitignore, Dockerfile, and scripts to reflect migration-based initialization [#459 Part 1]
Update documentation and CHANGELOG.md [#459 Part 1]
Implement HasData() seeding in OnModelCreating [#459 Part 2]
Replace test utilities CreateTable() and Seed() with MigrateAsync() [#459 Part 3]
Verify migration files contain only InsertData literals without application method calls [#459 Part 2] Migration file contents are not shown in this diff; cannot verify InitialCreate, SeedStarting11, and SeedSubstitutes migrations contain only EF Core-generated literals without application method calls.
Confirm PlayerData.MakeStarting11WithId() and WithId variants are removed [#459 Part 2] The diff shows HasData() calling these methods in OnModelCreating, but does not show whether the WithId() variants were subsequently removed from PlayerData.cs.

Possibly related issues

Possibly related PRs

🚥 Pre-merge checks | ✅ 2
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title follows Conventional Commits format (feat:), is descriptive and specific about the change (replacing pre-seeded db with EF Core migrations and HasData()), and is 78 characters, well under the 80-character limit.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/ef-core-migrate-async-at-startup
  • 🛠️ sync documentation: Commit on current branch
  • 🛠️ sync documentation: Create PR
  • 🛠️ enforce http error handling: Commit on current branch
  • 🛠️ enforce http error handling: Create PR
  • 🛠️ idiomatic review: Commit on current branch
  • 🛠️ idiomatic review: Create PR
  • 🛠️ verify api contract: Commit on current branch
  • 🛠️ verify api contract: Create PR

Warning

Review ran into problems

🔥 Problems

Timed out fetching pipeline failures after 30000ms


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

…459)

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@adr/0003-use-sqlite-for-data-storage.md`:
- Around line 21-22: The markdown heading "### Positive" is missing a blank line
before the following bullet list (MD022); edit the ADR content around the
heading "### Positive" and insert a single blank line between that heading and
the list item(s) (e.g., before "- Zero-config: ...") so the heading is separated
from the bullet list.

In
`@src/Dotnet.Samples.AspNetCore.WebApi/Extensions/ServiceCollectionExtensions.cs`:
- Around line 34-36: The code currently uses
Environment.GetEnvironmentVariable("STORAGE_PATH") directly when building
dataSource, which only falls back on null and will treat empty or whitespace as
a valid (but invalid-for-SQLite) path; change the logic in
ServiceCollectionExtensions so you first read var storagePath =
Environment.GetEnvironmentVariable("STORAGE_PATH"), then check
string.IsNullOrWhiteSpace(storagePath) and only use storagePath when it has
content, otherwise set dataSource to Path.Combine(AppContext.BaseDirectory,
"storage", "players-sqlite3.db"); update the dataSource assignment that
currently references Environment.GetEnvironmentVariable(...) accordingly.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: f4525fa1-edf5-487d-a33c-d5fd5c1f5892

📥 Commits

Reviewing files that changed from the base of the PR and between 66eca79 and 68d3f0d.

⛔ Files ignored due to path filters (14)
  • src/Dotnet.Samples.AspNetCore.WebApi/Migrations/20250414195445_SeedStarting11.Designer.cs is excluded by !**/Migrations/**, !**/*.Designer.cs
  • src/Dotnet.Samples.AspNetCore.WebApi/Migrations/20250414195445_SeedStarting11.cs is excluded by !**/Migrations/**
  • src/Dotnet.Samples.AspNetCore.WebApi/Migrations/20251221220614_SeedSubstitutes.Designer.cs is excluded by !**/Migrations/**, !**/*.Designer.cs
  • src/Dotnet.Samples.AspNetCore.WebApi/Migrations/20251221220614_SeedSubstitutes.cs is excluded by !**/Migrations/**
  • src/Dotnet.Samples.AspNetCore.WebApi/Migrations/20260329000000_NormalizePlayerDataset.Designer.cs is excluded by !**/Migrations/**, !**/*.Designer.cs
  • src/Dotnet.Samples.AspNetCore.WebApi/Migrations/20260329000000_NormalizePlayerDataset.cs is excluded by !**/Migrations/**
  • src/Dotnet.Samples.AspNetCore.WebApi/Migrations/20260409141647_InitialCreate.Designer.cs is excluded by !**/Migrations/**, !**/*.Designer.cs
  • src/Dotnet.Samples.AspNetCore.WebApi/Migrations/20260409141647_InitialCreate.cs is excluded by !**/Migrations/**
  • src/Dotnet.Samples.AspNetCore.WebApi/Migrations/20260409141707_SeedStarting11.Designer.cs is excluded by !**/Migrations/**, !**/*.Designer.cs
  • src/Dotnet.Samples.AspNetCore.WebApi/Migrations/20260409141707_SeedStarting11.cs is excluded by !**/Migrations/**
  • src/Dotnet.Samples.AspNetCore.WebApi/Migrations/20260409141721_SeedSubstitutes.Designer.cs is excluded by !**/Migrations/**, !**/*.Designer.cs
  • src/Dotnet.Samples.AspNetCore.WebApi/Migrations/20260409141721_SeedSubstitutes.cs is excluded by !**/Migrations/**
  • src/Dotnet.Samples.AspNetCore.WebApi/Migrations/PlayerDbContextModelSnapshot.cs is excluded by !**/Migrations/**
  • src/Dotnet.Samples.AspNetCore.WebApi/storage/players-sqlite3.db is excluded by !**/*.db, !**/storage/**, !**/*.db
📒 Files selected for processing (15)
  • .github/copilot-instructions.md
  • .gitignore
  • CHANGELOG.md
  • Dockerfile
  • README.md
  • adr/0003-use-sqlite-for-data-storage.md
  • scripts/entrypoint.sh
  • scripts/run-migrations-and-copy-database.sh
  • src/Dotnet.Samples.AspNetCore.WebApi/Data/PlayerDbContext.cs
  • src/Dotnet.Samples.AspNetCore.WebApi/Dotnet.Samples.AspNetCore.WebApi.csproj
  • src/Dotnet.Samples.AspNetCore.WebApi/Extensions/ServiceCollectionExtensions.cs
  • src/Dotnet.Samples.AspNetCore.WebApi/Program.cs
  • src/Dotnet.Samples.AspNetCore.WebApi/appsettings.Development.json
  • src/Dotnet.Samples.AspNetCore.WebApi/appsettings.json
  • test/Dotnet.Samples.AspNetCore.WebApi.Tests/Utilities/DatabaseFakes.cs
💤 Files with no reviewable changes (3)
  • src/Dotnet.Samples.AspNetCore.WebApi/Dotnet.Samples.AspNetCore.WebApi.csproj
  • Dockerfile
  • scripts/run-migrations-and-copy-database.sh

Comment thread adr/0003-use-sqlite-for-data-storage.md
Comment thread src/Dotnet.Samples.AspNetCore.WebApi/Extensions/ServiceCollectionExtensions.cs Outdated
nanotaboada and others added 2 commits April 9, 2026 11:49
…ties (#459)

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
…#459)

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud Bot commented Apr 9, 2026

@nanotaboada nanotaboada merged commit 7de7b87 into master Apr 9, 2026
9 checks passed
@nanotaboada nanotaboada deleted the feat/ef-core-migrate-async-at-startup branch April 9, 2026 15:41
@nanotaboada nanotaboada changed the title feat(data): replace pre-seeded db with EF Core migrations and HasData() (#459) feat(data): replace pre-seeded db with EF Core migrations and HasData() (#459) Apr 9, 2026
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.

Replace pre-seeded database file with EF Core auto-migration at startup and recreate migrations using HasData()

1 participant