Database Migrations
Entity Framework Core includes a powerful migration system. Ramsha builds on this foundation to provide a consistent, streamlined way to manage database changes during application development.
RamshaDesignTimeDbContextFactory Class
The foundation for creating migrations in Ramsha is the RamshaDesignTimeDbContextFactory<TModule, TDbContext> abstract class. This class implements the IDesignTimeDbContextFactory<TDbContext> interface and provides the infrastructure needed for EF Core Tools to create migrations in a Ramsha application.
The key responsibilities of this abstract class are:
- Initializing the Ramsha application module during design time
- Building the service provider with proper configuration
- Creating and configuring the DbContext instance for migration generation
- Handling environment-specific configuration loading
Overview
There are two distinct phases in the migration process:
- Creating Migrations - Generating migration files from model changes
- Applying Migrations - Updating the database with generated migrations
Creating Migrations
Migrations are always created using EF Core Tools with the Design-Time DbContext Factory pattern. This approach uses Microsoft's dotnet ef CLI tools along with a Design-Time DbContext Factory (IDesignTimeDbContextFactory<TContext>).
How the Design-Time Factory Works
When you create migrations, the following flow occurs:
- Developer runs
dotnet ef migrations add - EF Core Tools searches for an
IDesignTimeDbContextFactory<TContext>implementation - RamshaDesignTimeDbContext initializes the Ramsha application module
- Module builds services and registers the DbContext
- Factory creates DbContext instance with proper configuration
- EF Core generates migration files based on model changes
Implementation
1. Create Your Design-Time Factory
This class created by default if u create the project with Ramsha Soultions Templates, If not exist you can create new class:
public class AppDbContextDesignTimeFactory
: RamshaDesignTimeDbContext<AppModule, AppDbContext>
{
// Default implementation is sufficient for most cases
}
2. Install Required Package
dotnet add package Microsoft.EntityFrameworkCore.Tools
3. Migration Commands
Simple Project Structure:
# Add a new migration
dotnet ef migrations add InitialCreate
Clean Architecture Template:
# From startup layer path
dotnet ef migrations add InitialCreate --project ../MyApp.Persistence/MyApp.Persistence.csproj
# From persistence layer path
dotnet ef migrations add InitialCreate --startup-project ../MyApp.Startup/MyApp.Startup.csproj
Applying Migrations
Once migrations are created, you have two approaches to apply them to the database:
1. EF Core Tools Migration Application (Manual)
Apply migrations using the dotnet ef CLI tool:
# Simple project
dotnet ef database update
# Clean architecture
dotnet ef database update --project ../MyApp.Persistence/MyApp.Persistence.csproj
Best for: Development environments, testing, and CI/CD pipelines
2. Programmatic Migration Application (Automatic)
Apply migrations automatically through code during application startup:
public class AppModule : RamshaModule
{
public override async Task OnInitAsync(ApplicationInitializationContext context)
{
// Apply pending migrations on application startup
var dbContext = context.ServiceProvider.GetRequiredService<AppDbContext>();
await dbContext.Database.MigrateAsync();
}
}
Best for: Production deployments, containerized applications, and automatic updates
Configuration for Migration Creation
Migration-Specific Settings
Create appsettings.Migrations.json in your startup project for migration creation:
{
"ConnectionStrings": {
"Default": "Server=(localdb)\\mssqllocaldb;Database=DemoApp;Trusted_Connection=True;MultipleActiveResultSets=true"
}
}
Customizing Design-Time Configuration
public class AppDbContextDesignTimeFactory
: RamshaDesignTimeDbContext<AppModule, AppDbContext>
{
protected override IConfigurationRoot BuildConfiguration()
{
var environment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT")
?? "Development";
return new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{environment}.json", optional: true)
.AddJsonFile($"appsettings.Migrations.json", optional: true)
.AddEnvironmentVariables()
.AddUserSecrets<AppDbContextDesignTimeFactory>(optional: true)
.Build();
}
}
Migration Workflow Summary
-
Development Phase:
- Make model changes to your entities
- Run
dotnet ef migrations add <Name>to generate migration files - Review generated migration files
-
Application Phase (Choose One):
- Option A: Use
dotnet ef database update(development/CI) - Option B: Let application apply migrations automatically via
MigrateAsync()(production)
- Option A: Use