Overview
FullStackHero uses Entity Framework Core migrations to manage database schema changes. The architecture supports multi-tenancy with per-tenant databases.Migrations are stored in a separate project (
Migrations.PostgreSQL) and are tenant-aware.Migration Project Structure
DbContext and separate migration folder.
DbContext Configuration
Modules define their ownDbContext with tenant-aware configuration:
IdentityDbContext.cs
Common Migration Commands
Add Migration
Create a new migration after changing entities:Apply Migrations
Apply pending migrations to the database:In production, migrations are applied automatically on startup via
UseHeroMultiTenantDatabases().List Migrations
View all migrations and their status:Remove Last Migration
Remove the most recent migration (before applying):Generate SQL Script
Generate SQL for production deployment:Multi-Tenant Database Management
UseHeroMultiTenantDatabases
The application automatically applies migrations to all tenant databases on startup:Program.cs
Extensions.cs
Database Per Tenant
FSH supports two multi-tenancy strategies:Shared Database
Single database with tenant isolation
- Tenant ID column on all tables
- Automatic query filters
- Lower infrastructure cost
Database Per Tenant
Separate database for each tenant
- Complete data isolation
- Independent scaling
- Easier compliance (GDPR, etc.)
Entity Configuration
UseIEntityTypeConfiguration<T> to configure entities:
GroupConfiguration.cs
Migration Workflow
public class Group : ISoftDeletable
{
public Guid Id { get; private set; }
public string Name { get; private set; } = default!;
public string? Description { get; private set; }
// ... other properties
}
public class GroupConfiguration : IEntityTypeConfiguration<Group>
{
public void Configure(EntityTypeBuilder<Group> builder)
{
builder.ToTable("Groups", "identity");
builder.HasKey(g => g.Id);
builder.Property(g => g.Name).IsRequired().HasMaxLength(256);
// ... other configurations
}
}
dotnet ef migrations add AddGroups \
--project src/Playground/Migrations.PostgreSQL \
--startup-project src/Playground/Playground.Api \
--context IdentityDbContext
using Microsoft.EntityFrameworkCore.Migrations;
public partial class AddGroups : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Groups",
schema: "identity",
columns: table => new
{
Id = table.Column<Guid>(type: "uuid", nullable: false),
Name = table.Column<string>(type: "character varying(256)", maxLength: 256, nullable: false),
Description = table.Column<string>(type: "character varying(1024)", maxLength: 1024, nullable: true),
IsDefault = table.Column<bool>(type: "boolean", nullable: false),
// ... other columns
},
constraints: table =>
{
table.PrimaryKey("PK_Groups", x => x.Id);
});
migrationBuilder.CreateIndex(
name: "IX_Groups_Name",
schema: "identity",
table: "Groups",
column: "Name",
unique: true);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "Groups",
schema: "identity");
}
}
dotnet ef database update \
--project src/Playground/Migrations.PostgreSQL \
--startup-project src/Playground/Playground.Api \
--context IdentityDbContext
Migration Naming Conventions
Use descriptive names that explain the change:Troubleshooting
No DbContext was found
Error:No DbContext named 'IdentityDbContext' was found.
Solution: Always specify the context explicitly:
Build failed
Error: Migration creation fails due to build errors. Solution: Build the solution first:Pending migrations
Error: Database is out of sync with migrations. Solution: Apply pending migrations:Migration already applied
Error: Cannot remove migration that’s already applied. Solution: Check__EFMigrationsHistory table:
Best Practices
Always Review Migrations
Check the generated Up() and Down() methods before applying
Test Rollbacks
Verify the Down() method works correctly
Use Configurations
Define entity mappings in
IEntityTypeConfiguration<T> classesBackup Production
Always backup databases before applying migrations in production
Production Deployment
Option 1: Automatic Migration on Startup
The default approach (used byUseHeroMultiTenantDatabases()):
Option 2: SQL Scripts
Generate SQL scripts for DBA review:--idempotent flag ensures scripts can be run multiple times safely.
Next Steps
Creating Features
Build features that use your entities
Testing
Test database operations
Domain Entities
Design rich domain models
