Skip to content

Commit c915288

Browse files
authored
Merge pull request #334 from nanotaboada/feature/seed-substitute-players
feat: add 15 substitute players to database via migration
2 parents 33d017f + b9eadfc commit c915288

File tree

8 files changed

+587
-14
lines changed

8 files changed

+587
-14
lines changed

.github/copilot-instructions.md

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -294,11 +294,26 @@ dotnet ef database update --project src/Dotnet.Samples.AspNetCore.WebApi
294294
./scripts/run-migrations-and-copy-database.sh
295295
```
296296

297-
**Important**: The `run-migrations-and-copy-database.sh` script:
298-
- Resets the placeholder database file
299-
- Runs all migrations
300-
- Copies the generated database from `bin/Debug/net8.0/Data/` to `Data/`
301-
- Requires `dotnet ef` CLI tool installed globally
297+
**Database Workflow Explained:**
298+
299+
The project maintains a **pre-seeded database** at `storage/players-sqlite3.db` to support three use cases:
300+
1. **Clone & Run** - Developers can clone the repo and run immediately without manual DB setup
301+
2. **Recreate from Scratch** - Use the script to rebuild the database with all migrations
302+
3. **Docker** - Container gets a copy of the pre-seeded database on first startup
303+
304+
**How `run-migrations-and-copy-database.sh` works:**
305+
1. **Creates empty file** at `storage/players-sqlite3.db` (version-controlled source location)
306+
2. **Runs migrations** via `dotnet ef database update`
307+
- EF Core uses `AppContext.BaseDirectory/storage/players-sqlite3.db`
308+
- During migration, `AppContext.BaseDirectory` = `bin/Debug/net8.0/`
309+
- EF Core creates/updates database at `bin/Debug/net8.0/storage/players-sqlite3.db`
310+
- Applies all migrations: creates schema, seeds 26 players (11 starting + 15 substitutes)
311+
3. **Copies migration-applied database** from `bin/Debug/net8.0/storage/` back to `storage/`
312+
- Updates the version-controlled database with latest schema + seed data
313+
- This file is included in git and copied to build output via `.csproj` configuration
314+
315+
**Requirements:**
316+
- `dotnet ef` CLI tool installed globally (`dotnet tool install --global dotnet-ef`)
302317

303318
### Docker Operations
304319
```bash
@@ -325,9 +340,9 @@ docker compose down -v
325340
## 🚨 Common Issues & Workarounds
326341

327342
### Database Path Issues
328-
- **SQLite database location**: `storage/players-sqlite3.db` relative to binary output
329-
- **Container storage**: `/storage/players-sqlite3.db` (mounted volume)
330-
- **Environment variable**: `STORAGE_PATH` can override the default path in containers
343+
- **Development**: `storage/players-sqlite3.db` (source, copied to `bin/Debug/net8.0/storage/` during build)
344+
- **Container**: Pre-seeded database copied from image `/app/hold/` to volume `/storage/` on first run
345+
- **Runtime**: Application uses `AppContext.BaseDirectory/storage/players-sqlite3.db`
331346

332347
### Validation Patterns
333348
- **FluentValidation** runs in the validator class for input format/structure

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ src/Dotnet.Samples.AspNetCore.WebApi/
7575
│ ├── Player.cs
7676
│ ├── PlayerRequestModel.cs
7777
│ └── PlayerResponseModel.cs
78-
├── Data/ # EF Core DbContext
78+
├── Data/ # EF Core DbContext and migrations
7979
│ └── PlayerDbContext.cs
8080
├── Mappings/ # AutoMapper profiles
8181
│ └── PlayerMappingProfile.cs

scripts/run-migrations-and-copy-database.sh

100755100644
Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,11 @@ DATA_FILE="players-sqlite3.db"
55
PROJECT_ROOT_PATH="src/Dotnet.Samples.AspNetCore.WebApi"
66
PROJECT_BASE_PATH="$PROJECT_ROOT_PATH/bin/Debug/net8.0"
77

8-
SOURCE_FILE_PATH="$PROJECT_BASE_PATH/Data/$DATA_FILE"
9-
TARGET_FILE_PATH="$PROJECT_ROOT_PATH/Data/$DATA_FILE"
8+
SOURCE_FILE_PATH="$PROJECT_BASE_PATH/storage/$DATA_FILE"
9+
TARGET_FILE_PATH="$PROJECT_ROOT_PATH/storage/$DATA_FILE"
1010

11+
# log prints a formatted log message prefixed by an emoji and timestamp, followed by the log level and message.
12+
# Parameters: emoji — emoji or symbol to prefix the entry; level — severity or level label; message — the log text.
1113
log() {
1214
local emoji=$1
1315
local level=$2
@@ -60,4 +62,4 @@ if [ -f "$TARGET_FILE_PATH" ]; then
6062
else
6163
log "⚠️" "WARNING" "Something went wrong. The destination file was not found."
6264
exit 1
63-
fi
65+
fi

src/Dotnet.Samples.AspNetCore.WebApi/Migrations/20251221220614_SeedSubstitutes.Designer.cs

Lines changed: 69 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
using Dotnet.Samples.AspNetCore.WebApi.Utilities;
2+
using Microsoft.EntityFrameworkCore.Migrations;
3+
4+
#nullable disable
5+
6+
namespace Dotnet.Samples.AspNetCore.WebApi.Migrations
7+
{
8+
/// <inheritdoc />
9+
public partial class SeedSubstitutes : Migration
10+
{
11+
/// <inheritdoc />
12+
protected override void Up(MigrationBuilder migrationBuilder)
13+
{
14+
var substitutes = PlayerData.GetSubstitutesWithId();
15+
16+
foreach (var player in substitutes)
17+
{
18+
migrationBuilder.InsertData(
19+
table: "Players",
20+
columns:
21+
[
22+
"Id",
23+
"FirstName",
24+
"MiddleName",
25+
"LastName",
26+
"DateOfBirth",
27+
"SquadNumber",
28+
"Position",
29+
"AbbrPosition",
30+
"Team",
31+
"League",
32+
"Starting11"
33+
],
34+
values: new object[]
35+
{
36+
player.Id,
37+
player.FirstName,
38+
player.MiddleName,
39+
player.LastName,
40+
player.DateOfBirth,
41+
player.SquadNumber,
42+
player.Position,
43+
player.AbbrPosition,
44+
player.Team,
45+
player.League,
46+
player.Starting11
47+
}
48+
);
49+
}
50+
}
51+
52+
/// <inheritdoc />
53+
protected override void Down(MigrationBuilder migrationBuilder)
54+
{
55+
var substitutes = PlayerData.GetSubstitutesWithId();
56+
foreach (var player in substitutes)
57+
{
58+
migrationBuilder.DeleteData(table: "Players", keyColumn: "Id", keyValue: player.Id);
59+
}
60+
}
61+
}
62+
}

src/Dotnet.Samples.AspNetCore.WebApi/Migrations/PlayerDbContextModelSnapshot.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ partial class PlayerDbContextModelSnapshot : ModelSnapshot
1515
protected override void BuildModel(ModelBuilder modelBuilder)
1616
{
1717
#pragma warning disable 612, 618
18-
modelBuilder.HasAnnotation("ProductVersion", "9.0.4");
18+
modelBuilder.HasAnnotation("ProductVersion", "9.0.11");
1919

2020
modelBuilder.Entity("Dotnet.Samples.AspNetCore.WebApi.Models.Player", b =>
2121
{

0 commit comments

Comments
 (0)