Skip to content

Commit d1073da

Browse files
authored
Merge branch 'master' into dependabot/github_actions/docker/setup-buildx-action-3.12.0
2 parents 3d5b7a4 + e208f1d commit d1073da

11 files changed

Lines changed: 593 additions & 20 deletions

File tree

.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: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,19 @@ 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
1416
local message=$3
1517
local timestamp
1618
timestamp=$(date +"%Y-%m-%d %H:%M:%S")
1719
echo "$emoji [$timestamp] [$level] $message"
20+
return 0
1821
}
1922

2023
# Check if the EF Core CLI tool is installed
@@ -31,18 +34,18 @@ touch "$TARGET_FILE_PATH"
3134
# Run the database migration
3235
log "" "INFO" "Running EF Core database migration for project at '$PROJECT_ROOT_PATH'..."
3336
dotnet ef database update --project "$PROJECT_ROOT_PATH"
34-
if [ $? -ne 0 ]; then
37+
if [[ $? -ne 0 ]]; then
3538
log "" "ERROR" "Migration failed. See error above."
3639
exit 1
3740
fi
3841

3942
# Check and copy database
40-
if [ -f "$SOURCE_FILE_PATH" ]; then
43+
if [[ -f "$SOURCE_FILE_PATH" ]]; then
4144
log "" "INFO" "Found database at '$SOURCE_FILE_PATH'"
4245
log "" "INFO" "Copying to '$TARGET_FILE_PATH'..."
4346
cp -f "$SOURCE_FILE_PATH" "$TARGET_FILE_PATH"
4447

45-
if [ $? -eq 0 ]; then
48+
if [[ $? -eq 0 ]]; then
4649
log "" "INFO" "Database successfully copied to '$TARGET_FILE_PATH'"
4750
else
4851
log "" "ERROR" "Failed to copy the database file."
@@ -55,7 +58,7 @@ else
5558
fi
5659

5760
# Confirm destination file exists
58-
if [ -f "$TARGET_FILE_PATH" ]; then
61+
if [[ -f "$TARGET_FILE_PATH" ]]; then
5962
log "" "INFO" "Done. The database is now available at '$TARGET_FILE_PATH'"
6063
else
6164
log "⚠️" "WARNING" "Something went wrong. The destination file was not found."

src/Dotnet.Samples.AspNetCore.WebApi/Controllers/PlayerController.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ [FromBody] PlayerRequestModel player
177177
.ToArray();
178178

179179
logger.LogWarning(
180-
"PUT /players/{squadNumber} validation failed: {@Errors}",
180+
"PUT /players/{SquadNumber} validation failed: {@Errors}",
181181
squadNumber,
182182
errors
183183
);

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
{

src/Dotnet.Samples.AspNetCore.WebApi/Models/PlayerRequestModel.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ public class PlayerRequestModel
2020

2121
public DateTime? DateOfBirth { get; set; }
2222

23-
public int SquadNumber { get; set; }
23+
public required int SquadNumber { get; set; }
2424

2525
public string? AbbrPosition { get; set; }
2626

0 commit comments

Comments
 (0)