---
name: step-seed
description: Populate database with test data
next_step: null
---

# Database Seed

## YOUR TASK:

Populate the database with test or initial data using EF Core conventions.

**Requires:** `steps/shared/step-00-init.md` completed

---

## COMPLIANCE:

| FORBIDDEN | REQUIRED |
|-----------|----------|
| SQL scripts in repo | `HasData()` in configurations |
| `sqlcmd` with INSERT | `IDataSeeder` classes |
| `migrationBuilder.Sql()` INSERT | EF Core typed migrations |

---

## EXECUTION SEQUENCE:

### 1. Environment Check

```bash
# Validate required variables from step-00-init
for VAR_NAME in DBCONTEXT DBCONTEXT_TYPE INFRA_PROJECT STARTUP_PROJECT SELECTED_ENV; do
  eval VAR_VALUE=\$$VAR_NAME
  if [ -z "$VAR_VALUE" ]; then
    echo "ERROR: Required variable $VAR_NAME is not set"
    echo "Run step-00-init first"
    exit 1
  fi
done

echo "Seed Configuration"
echo "=================="
echo ""
echo "DbContext:   $DBCONTEXT ($DBCONTEXT_TYPE)"
echo "Environment: $SELECTED_ENV"
echo "Database:    $DATABASE_NAME"

# Block production
block_production
```

### 2. Detect Available Seed Methods

```bash
echo ""
echo "Detecting seed methods..."

SEED_METHODS=""

# HasData() in configurations (RECOMMENDED)
if grep -rq "\.HasData(" . --include="*.cs" 2>/dev/null; then
  SEED_METHODS+=" hasdata"
  echo "  - HasData(): Found"
fi

# IDataSeeder classes
if grep -rq "IDataSeeder\|class.*Seeder" . --include="*.cs" 2>/dev/null; then
  SEED_METHODS+=" seeder-class"
  echo "  - Seeder classes: Found"
fi

# --seed CLI argument
if grep -q "\-\-seed" ./src/*/Program.cs 2>/dev/null; then
  SEED_METHODS+=" cli-argument"
  echo "  - CLI --seed: Found"
fi

# WARNING: SQL scripts detected
if [ -f "./scripts/seed.sql" ] || find . -name "seed*.sql" 2>/dev/null | grep -q .; then
  echo ""
  echo "WARNING: SQL seed scripts detected - FORBIDDEN by conventions"
  echo "Migrate to HasData() or IDataSeeder"
fi

if [ -z "$SEED_METHODS" ]; then
  echo "  No seed methods found"
fi
```

### 3. Select Method

**If multiple methods available:**

```yaml
AskUserQuestion:
  header: "Seed"
  question: "Which seed method to use?"
  options:
    - label: "HasData (Recommended)"
      description: "Via EF Core migrations"
    - label: "Seeder Class"
      description: "Run DbSeeder/DataSeeder"
    - label: "CLI --seed"
      description: "Launch app with --seed"
  multiSelect: false
```

### 4. Execute Seed

**HasData method:**

```bash
echo ""
echo "HasData is applied via migrations."
echo "Running database update to ensure all HasData is applied..."

dotnet ef database update \
  --context "$DBCONTEXT" \
  --project "$INFRA_PROJECT" \
  --startup-project "$STARTUP_PROJECT"
```

**Seeder Class method:**

```bash
echo ""
echo "Running seeder class..."

dotnet run --project "$STARTUP_PROJECT" -- --seed
EXIT_CODE=$?

if [ $EXIT_CODE -ne 0 ]; then
  echo "Seed command failed or not supported (exit code: $EXIT_CODE)"
  echo "Check if --seed argument is implemented in Program.cs"
fi
```

**CLI argument method:**

```bash
echo ""
echo "Running application with --seed..."

dotnet run --project "$STARTUP_PROJECT" -- --seed
```

### 5. Verify (Optional)

```bash
echo ""
echo "Verifying seed data..."

# Quick check - count records in key tables
# This is application-specific
```

### 6. Summary

```bash
echo ""
echo "==========================================="
echo "SEED COMPLETE"
echo "==========================================="
echo ""
echo "Database:    $DATABASE_NAME"
echo "Environment: $SELECTED_ENV"
echo "Method:      $SEED_METHOD"
echo ""
echo "Compliance:  EF Core native, No raw SQL"
echo ""
echo "==========================================="
echo ""
echo "Next steps:"
echo "  /efcore db-status    # Check status"
echo "  dotnet run           # Start application"
echo ""
```

---

## OUTPUT FORMAT:

```
SEED COMPLETE
=============
Database:    {database_name}
Environment: {env}
Method:      {hasdata | seeder-class | cli-argument}

Compliance:  EF Core native, No raw SQL

Next: /efcore db-status, dotnet run
```

---

## NO SEED METHODS FOUND:

If no seed methods detected, display guide:

```
SEED SETUP GUIDE
================

Option 1: HasData() in Configuration (RECOMMENDED)
--------------------------------------------------
// In UserConfiguration.cs
builder.HasData(new User {
    Id = Guid.Parse("7f3c9a2e-8d1b-4e5f-a6c8-9b4d2f7e1a3c"),
    Name = "Admin",
    Email = "admin@example.com"
});

// Then run:
dotnet ef migrations add SeedData

Option 2: IDataSeeder Class
---------------------------
public class UserSeeder : IDataSeeder
{
    public async Task SeedAsync(DbContext context)
    {
        if (!await context.Users.AnyAsync())
        {
            context.Users.Add(new User { ... });
            await context.SaveChangesAsync();
        }
    }
}

// Register in Program.cs and call via --seed argument
```

---

## MIGRATION FROM SQL:

```csharp
// BEFORE (FORBIDDEN): scripts/seed.sql
INSERT INTO Users (Id, Name) VALUES (1, 'Admin');

// AFTER (CORRECT): UserConfiguration.cs
builder.HasData(new User {
    Id = Guid.Parse("7f3c9a2e-8d1b-4e5f-a6c8-9b4d2f7e1a3c"),
    Name = "Admin"
});
// Then: dotnet ef migrations add SeedData
```

---

## BOTH CONTEXTS:

If `RUN_BOTH=true` (auto-detected for client projects with SmartStack NuGet):

Run the seed sequence for both contexts, in order:

```bash
# 1. Seed CoreDbContext first (system data: Users, Roles, Permissions...)
echo "=== Seeding CoreDbContext (core schema) ==="
DBCONTEXT="CoreDbContext"
# Run steps 2-6 with CoreDbContext...

# 2. Then ExtensionsDbContext (client data)
echo ""
echo "=== Seeding ExtensionsDbContext (extensions schema) ==="
DBCONTEXT="ExtensionsDbContext"
# Run steps 2-6 with ExtensionsDbContext...
```

**Order matters:** Core MUST be seeded first (Extensions may reference Core data via foreign keys).

---

## OPTIONS:

| Option | Description |
|--------|-------------|
| `--env {name}` | Use appsettings.{name}.json |
| `--context {name}` | Specify DbContext |
| `--method {name}` | Force seed method (hasdata, seeder-class, cli-argument) |

---

## COMPLETION:

Seed data applied. Use `/efcore db-status` to verify.
