Description
Several solutions were considered, but for now, we have moved Database Migrations to the CI/CD flow in GitHub using Entity Framework Core migrations.
See: Move database migrations to CI/CD with SQL preview on pull requests and approval workflow
Problem
In .NET Entity Framework, there can be several database schema migrations. However, between each Database migration, there might be the need to have data migration don by code code.Example:
- Schema migration: Add new FirstName and LastName columns to the Users table that allows null
- Data migration that populates the new columns from the existing Users.DisplayName column using C# code
- Schema migration: Remove the null check and delete the old DisplayName column
This is just a simple example. The solution should handle that many complex migrations are run in a certain order, if a system has not been updated for some time (e.g. Schema, Data, Schema, Schema, Data, Schema, Data).
How can I create a good migration strategy that runs as part of the Application startup?
Solution 1
Use SQL .dbproj and DacPac: Power your DevOps Development with SQL Server Containers
Solution 2
Managing database migrations and code transformations in a sequential and reliable manner is indeed an important aspect of maintaining a robust application, especially in a complex domain-driven design project. Your problem is about orchestrating these operations in a way that ensures database integrity and data consistency.
For .NET and Entity Framework, you have a tool called EF Migrations which can handle database schema changes. However, EF Migrations doesn't inherently support code migrations that transform data between schema migrations.
Here is an approach you might consider:
- Separate Schema Migrations and Data Migrations: Separate schema migrations (handled by EF Migrations) and data migrations (custom scripts for data transformations).
- Sequential Naming Convention: Adopt a naming convention for your migrations that includes a sequence number (e.g.,
001_AddColumns
,002_PopulateColumns
,003_RemoveNullCheck
). This will ensure that migrations are executed in the correct order. - Custom Migration Runner: Implement a custom migration runner that executes at application startup. This runner should:
-
Run the EF Migrations up to the point where a data migration is needed.
-
Run the corresponding data migration scripts.
-
Continue with the rest of the EF Migrations.
This could be achieved by using the
DbContext.Database.Migrate()
method to apply the EF
Migrations and a custom method to execute the data migrations. The data migration scripts could be SQL scripts or C# scripts depending on the complexity of the data transformations.
- Idempotent Migrations: Make sure your migrations are idempotent - that is, they can be run multiple times without causing issues. This is important as migrations might fail and need to be rerun.
- Test Your Migrations: Always test your migrations, ideally in an environment that mirrors your production environment.
This solution allows you to manage both schema migrations and data transformations in a sequential manner. It also makes sure the order of operations is preserved when you deploy to different environments.
Remember that handling migrations this way could potentially cause longer downtimes during deployment, especially for large data migrations. So, you need to plan your deployments carefully.
Solution 3
A more naïve approach would be to run migration as part of the application startup. If not done carefully this might cause race conditions. One way to avoid Race conditions is to use "Init containers":
Generally available: Init containers in Azure Container Apps
Published date: August 16, 2023
The init containers feature in Azure Container Apps is now generally available. Init containers are specialized containers that run to completion before application containers are started in a replica, and they can contain utilities or setup scripts not present in your container app image. Init containers are useful for performing initialization logic such as setting up accounts, running setup scripts, and configuring databases.To learn more, visit: https://aka.ms/aca/init-containers
Metadata
Metadata
Assignees
Type
Projects
Status