Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 23 additions & 8 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -294,11 +294,26 @@ dotnet ef database update --project src/Dotnet.Samples.AspNetCore.WebApi
./scripts/run-migrations-and-copy-database.sh
```

**Important**: The `run-migrations-and-copy-database.sh` script:
- Resets the placeholder database file
- Runs all migrations
- Copies the generated database from `bin/Debug/net8.0/Data/` to `Data/`
- Requires `dotnet ef` CLI tool installed globally
**Database Workflow Explained:**

The project maintains a **pre-seeded database** at `storage/players-sqlite3.db` to support three use cases:
1. **Clone & Run** - Developers can clone the repo and run immediately without manual DB setup
2. **Recreate from Scratch** - Use the script to rebuild the database with all migrations
3. **Docker** - Container gets a copy of the pre-seeded database on first startup

**How `run-migrations-and-copy-database.sh` works:**
1. **Creates empty file** at `storage/players-sqlite3.db` (version-controlled source location)
2. **Runs migrations** via `dotnet ef database update`
- EF Core uses `AppContext.BaseDirectory/storage/players-sqlite3.db`
- During migration, `AppContext.BaseDirectory` = `bin/Debug/net8.0/`
- EF Core creates/updates database at `bin/Debug/net8.0/storage/players-sqlite3.db`
- Applies all migrations: creates schema, seeds 26 players (11 starting + 15 substitutes)
3. **Copies migration-applied database** from `bin/Debug/net8.0/storage/` back to `storage/`
- Updates the version-controlled database with latest schema + seed data
- This file is included in git and copied to build output via `.csproj` configuration

**Requirements:**
- `dotnet ef` CLI tool installed globally (`dotnet tool install --global dotnet-ef`)

### Docker Operations
```bash
Expand All @@ -325,9 +340,9 @@ docker compose down -v
## 🚨 Common Issues & Workarounds

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

### Validation Patterns
- **FluentValidation** runs in the validator class for input format/structure
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ src/Dotnet.Samples.AspNetCore.WebApi/
│ ├── Player.cs
│ ├── PlayerRequestModel.cs
│ └── PlayerResponseModel.cs
├── Data/ # EF Core DbContext
├── Data/ # EF Core DbContext and migrations
│ └── PlayerDbContext.cs
├── Mappings/ # AutoMapper profiles
│ └── PlayerMappingProfile.cs
Expand Down
8 changes: 5 additions & 3 deletions scripts/run-migrations-and-copy-database.sh
100755 → 100644
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@ DATA_FILE="players-sqlite3.db"
PROJECT_ROOT_PATH="src/Dotnet.Samples.AspNetCore.WebApi"
PROJECT_BASE_PATH="$PROJECT_ROOT_PATH/bin/Debug/net8.0"

SOURCE_FILE_PATH="$PROJECT_BASE_PATH/Data/$DATA_FILE"
TARGET_FILE_PATH="$PROJECT_ROOT_PATH/Data/$DATA_FILE"
SOURCE_FILE_PATH="$PROJECT_BASE_PATH/storage/$DATA_FILE"
TARGET_FILE_PATH="$PROJECT_ROOT_PATH/storage/$DATA_FILE"

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

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
using Dotnet.Samples.AspNetCore.WebApi.Utilities;
using Microsoft.EntityFrameworkCore.Migrations;

#nullable disable

namespace Dotnet.Samples.AspNetCore.WebApi.Migrations
{
/// <inheritdoc />
public partial class SeedSubstitutes : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
var substitutes = PlayerData.GetSubstitutesWithId();

foreach (var player in substitutes)
{
migrationBuilder.InsertData(
table: "Players",
columns:
[
"Id",
"FirstName",
"MiddleName",
"LastName",
"DateOfBirth",
"SquadNumber",
"Position",
"AbbrPosition",
"Team",
"League",
"Starting11"
],
values: new object[]
{
player.Id,
player.FirstName,
player.MiddleName,
player.LastName,
player.DateOfBirth,
player.SquadNumber,
player.Position,
player.AbbrPosition,
player.Team,
player.League,
player.Starting11
}
);
}
}

/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
var substitutes = PlayerData.GetSubstitutesWithId();
foreach (var player in substitutes)
{
migrationBuilder.DeleteData(table: "Players", keyColumn: "Id", keyValue: player.Id);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ partial class PlayerDbContextModelSnapshot : ModelSnapshot
protected override void BuildModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder.HasAnnotation("ProductVersion", "9.0.4");
modelBuilder.HasAnnotation("ProductVersion", "9.0.11");

modelBuilder.Entity("Dotnet.Samples.AspNetCore.WebApi.Models.Player", b =>
{
Expand Down
Loading