githubEdit

EF Core Migrations

Complete guide to working with Entity Framework Core migrations in Elsa Workflows v3, including custom migrations, DbContext management, and versioning strategies.

This guide explains how Elsa Workflows uses Entity Framework Core migrations and how to customize them for your needs. Whether you want to add your own entities to the Elsa database or maintain separate migration strategies, this guide covers the essential patterns.

Overview

Elsa Workflows uses Entity Framework Core (EF Core) for relational database persistence and includes built-in migrations that manage the database schema. Understanding how these migrations work is essential when:

  • Adding custom entities to the Elsa database

  • Generating combined migrations for Elsa + your application

  • Managing schema changes during upgrades

  • Working with multiple databases or contexts

Elsa's DbContext Architecture

Elsa uses two separate DbContext classes to organize persistence concerns:

ManagementElsaDbContext

Purpose: Stores workflow definitions and instances

Key Tables:

  • WorkflowDefinitions - Published and draft workflow definitions with version history

  • WorkflowInstances - Active and historical workflow execution state

Typical Usage:

  • Workflow Designer (Studio) reads/writes definitions

  • Workflow Runtime creates and updates instances during execution

RuntimeElsaDbContext

Purpose: Stores runtime operational data

Key Tables:

  • Bookmarks - Workflow suspension points for event-driven resumption

  • WorkflowInboxMessages - Incoming messages for workflow correlation

  • ActivityExecutionRecords - Detailed activity execution history

  • WorkflowExecutionLogRecords - Execution logs for debugging and auditing

Typical Usage:

  • Bookmark resolution when external events trigger workflows

  • Workflow inbox for asynchronous message handling

  • Execution log queries for monitoring and troubleshooting

Note: Both contexts can use the same physical database but maintain separate migration histories, or they can use separate databases for scaling and isolation.

How Elsa Migrations Work

Built-in Migrations

Elsa ships with complete migrations that create and manage the database schema across versions. These migrations are embedded in the Elsa NuGet packages (Elsa.EntityFrameworkCore.SqlServer, Elsa.EntityFrameworkCore.PostgreSQL, etc.).

Migration Naming Convention:

  • Migrations follow a timestamped pattern: YYYYMMDDHHMMSS_DescriptionOfChange

  • Example: 20240315120000_InitialCreate, 20240520093000_AddWorkflowInbox

Automatic Application:

Elsa can apply migrations automatically on startup:

⚠️ Warning: Automatic migrations (RunMigrations = true) are convenient for development but not recommended for production. Use controlled migration deployment in production environments.

Manual Migration Application

For production deployments, apply migrations manually:

Migration History

EF Core tracks applied migrations in the __EFMigrationsHistory table:

This table ensures migrations are only applied once and enables EF Core to understand the current schema version.

Adding Custom Entities to Elsa's Database

A common scenario is adding your own entities to the same database used by Elsa. This approach offers several benefits:

Benefits:

  • Single database simplifies deployment and management

  • Share transaction scope between Elsa and your entities

  • Unified backup and recovery

  • Simplified connection string management

Trade-offs:

  • Couples your schema to Elsa's schema

  • Requires careful migration management

  • Elsa version upgrades may require migration coordination

Strategy: Separate DbContext with Shared Database

The recommended approach is to create your own DbContext that references the same database but maintains independent migrations:

1. Create Your DbContext:

2. Register Your DbContext in Program.cs:

3. Configure Design-Time DbContext Factory (Required for Migrations):

Create a file ApplicationDbContextFactory.cs in your project root:

💡 Tip: Alternatively, you can specify the connection string via the --connection parameter when running dotnet ef commands instead of hardcoding it in the factory.

4. Generate Your Migrations:

5. Managing Updates:

When you add or modify entities:

Project Structure

A typical project structure with custom migrations:

Elsa's migrations remain in the Elsa NuGet packages and are applied separately.

Migration Commands Reference

Common EF Core CLI Commands

Install/Update EF Tools:

Add a New Migration:

Apply Migrations:

Generate SQL Scripts:

List Migrations:

Remove Last Migration (if not applied):

Drop Database (Caution!):

Specifying Connection Strings

Via Command Line:

Via Environment Variable:

Working with Multiple Contexts

When managing both Elsa contexts and your own:

Migration Strategies

Strategy 1: Single Shared Database

Description: Elsa and your application share a single database with separate contexts and independent migrations.

Configuration:

Pros:

  • ✅ Simple deployment and connection management

  • ✅ Share transaction scope between Elsa and app data

  • ✅ Single backup/restore process

Cons:

  • ❌ All schemas coupled in one database

  • ❌ Difficult to scale components independently

  • ❌ Schema changes impact all consumers

Best For: Small to medium applications, single-server deployments, development environments

Strategy 2: Separate Databases

Description: Elsa uses one database, your application uses another.

Configuration:

Pros:

  • ✅ Clear separation of concerns

  • ✅ Independent scaling of Elsa and app databases

  • ✅ Different backup/retention policies

  • ✅ Easier to upgrade Elsa without impacting app schema

Cons:

  • ❌ No shared transactions across databases

  • ❌ More complex connection management

  • ❌ Two backup/restore processes

Best For: Large applications, microservices architectures, scenarios requiring independent scaling

Strategy 3: Split Elsa Management and Runtime

Description: Separate databases for Elsa's management and runtime contexts.

Configuration:

Pros:

  • ✅ Scale management (definitions) separately from runtime (executions)

  • ✅ Different retention policies (keep definitions longer, purge old executions)

  • ✅ Isolate high-volume runtime data from stable definition data

Cons:

  • ❌ More infrastructure to manage

  • ❌ Additional connection configuration

Best For: High-throughput scenarios, compliance requirements, environments with different SLAs for definitions vs. execution data

Handling Elsa Version Upgrades

Review Release Notes

When upgrading Elsa to a new version:

  1. Check Release Notes - Review migration changes in the Elsa Core Release Notesarrow-up-right

  2. Review Migration Files - Examine new migrations in the updated NuGet packages

  3. Test in Staging - Apply migrations in a non-production environment first

  4. Backup Before Upgrade - Always backup databases before applying migrations

Upgrade Process

1. Update NuGet Packages:

2. Review Pending Migrations:

3. Generate SQL Scripts for Review:

4. Apply Migrations:

5. Rolling Upgrades (Clustered Environments):

For zero-downtime upgrades:

  1. Apply backward-compatible database migrations first

  2. Deploy new application version to nodes one at a time

  3. Monitor for errors during the transition

  4. Keep previous version ready for rollback

Rollback Strategy

If a migration causes issues:

1. Rollback Database:

2. Restore from Backup:

3. Revert Application Version:

Troubleshooting

Common Issues

Error: "The term 'dotnet-ef' is not recognized"

Cause: EF Core tools not installed.

Solution:

Error: "Unable to create an object of type 'ApplicationDbContext'"

Cause: Missing design-time DbContext factory or configuration.

Solution: Create a IDesignTimeDbContextFactory<T> implementation as shown above, or specify the connection string via command-line parameter.

Error: "The migration has already been applied to the database"

Cause: Migration already applied (informational).

Solution: No action needed. This is normal if the database is up to date.

Error: "Cannot find compilation library location for package"

Cause: Project not built before running dotnet ef commands.

Solution:

Error: "Pending model changes detected"

Cause: Entity model changes not captured in a migration.

Solution:

Diagnostic Commands

Check Current Migration Status:

View Last Migration Details:

Test Connection:

For Maintainers

Elsa Core Issue Reference

This guidance addresses elsa-core issue #6355arrow-up-right, which requests clearer documentation on EF Core migration strategies and custom entity integration.

Key Requirements from Issue:

  • ✅ Document Elsa's DbContext architecture

  • ✅ Show how to add custom entities to Elsa's database

  • ✅ Provide migration strategy guidance

  • ✅ Explain manual vs. automatic migration approaches

  • ✅ Cover version upgrade scenarios

Schema Versioning Best Practices

For teams maintaining Elsa-based applications:

  1. Keep Migrations in Source Control - Commit all migration files alongside application code

  2. Use Semantic Versioning - Tag releases with versions that correspond to schema versions

  3. Document Schema Changes - Maintain a CHANGELOG for notable schema modifications

  4. Test Migrations - Include migration testing in CI/CD pipelines

  5. Database Branching - Consider separate databases per branch for feature development

Next Steps

  • Decide on a migration strategy (single vs. separate databases)

  • Create your DbContext if adding custom entities

  • Generate and review migrations before applying

  • Implement backup procedures before schema changes

  • Automate migration deployment in your CI/CD pipeline


Last Updated: 2025-12-01

Addresses Issues: #74 (generating custom EF Core migrations), #11 (persistence configuration), references elsa-core #6355

Last updated