Execute Data Migration
Before performing the migration, you need to be sure that your environment is properly prepared. At the time of writing this documentation, my environment consists of the following:
Tool | Version |
---|---|
.NET SDK | 7.0.306 |
dotnet-ef | 7.0.9 |
SQL Server | 2022 Developer Edition |
SQL Server Management Studio | 19.1 |
Azure Data Studio | 1.45.0 |
Additionally, you should have access to a SQL Server with AdventureWorks installed.
The database configuration can be found in connections.json:
{
"Origin": {
"Server": ".\\DevSql",
"Database": "AdventureWorks2022"
},
"Target": {
"Server": ".\\DevSql",
"Database": "v2-schema"
},
"ConnectionStrings": {
"Migration": "Server=.\\DevSql;Trusted_Connection=true;TrustServerCertificate=true;Database=v2-migration"
}
}
If you need to consolidate multiple origin databases into a single target database, run the migration with different connections.json
files where each origin database has a corresponding origin ConnectorConfig
and migration connection string.
The migration and target databases should always be in sync. If on of these databases is removed and you want to perform a new migration, the other database should also be removed prior to the migration.
Database Preparation
The migration and target databases have corresponding Entity Framework configuration in this project:
- Migration - MigratorContext
- Target - AppDbContext
This project also defines tasks for dropping and updating these databases:
Alternatively, these commands can be executed from a terminal:
Task | Directory | Command |
---|---|---|
Drop App DB | /src/App | dotnet ef database drop -f |
Update App DB | /src/App | dotnet ef database update |
Drop Migration DB | /src/Core | dotnet ef database drop -f |
Update Migration DB | /src/Core | dotnet ef database update |
Each of the following section start off assuming that you are starting with a blank migration and target database. The CLI automatically initializes the migration database according to the connection string if it does not exist, so you only need to drop the database between CLI runs. The target database, however, does not and needs to be dropped and updated between CLI runs.
Additionally, all of the CLI runs are executed from the /src/Cli/bin/Debug/net7.0/
directory after the project has been built.
Migrate a Single Entity
The simplest form of data migration is to migrate a table that has no dependencies via its migration command. Doing so will only import the data from that specific table and nothing else.
To demonstrate this, run .\migrator.exe migrate department
:
Querying the target database, you can see that the Department
records have been successfully migrated:
Additionally, querying the migration database, you can see that the recorded migration logs:
Migrate Entities Recursively
If you're performing a fresh migrating targeting a table with dependencies, the migrated data will include the records for the dependent data along with the targeted table records.
To demonstrate this, run .\migrator.exe migrate employee
:
Querying the target database, you can see that the Employee
records have been migrated along with their dependent Department
records:
If .\migrator.exe migrate contactinfo
had been run instead, all ContactInfo
records would have also caused their dependent Employee
records to be migrated as well as their dependent Department
records.
By building in calls to Translator.EnsureMigrated
for each dependency inside of an OnMigrate
callback, we can ensure that the full dependency tree is migrated recursively.
Additionally, querying the migration database, you can see the recorded migration logs:
Full Migration
Performing a full migration will execute the Translator.Migrate()
migrations in the order they are specified in the FullCommand
.
To demonstrate this, run .\migrator.exe migrate full
:
Querying the target database, you can see that all records from all tables have been migrated:
If data were ever migrated as a dependency before the migration for its table is executed, that record would be skipped during the validation phase since the record with that key would already be in the migration database. This ensures that there is no duplication of records polluting the migration.
Additionally, querying the migration database, you can see the recorded migration logs: