We are starting a new application with with .NET Core, EF Core and Postgres - we're really liking the migrations :-)
However, I've found a problem that I can't figure out how to work around. In some of our migrations, we use the
DbContext to load records, run some business logic, and resave the records. We also run
database.Context.Migrate() when the web server starts, so it always runs.
This all works fine (so far).
Unfortunately it works right up until the model is changed at a later point. Consider the following migration order:
OrderLinemodels. Add the schema migrations to load the structures
A business rule changes, so we need to set a value on the
Order record based on some business logic . We create a data migration where we load the
DbContext, run the code, and run
At this point, everything is fine.
We need to add a schema migration with a new field to the
Here, things break. If the database has not had migration 2 applied, the
Migrate() command errors as when applying migration 2, EF is trying to generate a select statement that includes the new field in 3.
I'm not sure where the problem actually is in the process though: should we not be using the
DbContext in the migration (and hand-code SQL statements)? Should we be explicitly be doing projections on every record read so that we know exactly what we're doing?
In your example, 1 and 3 are Schema Migrations and 2 is a Data Migration.
Since Entity Framework Core will generate queries based off the current models in code, and not the current state of the database, there is two options for handling Data Migrations.
Perform Data Migrations In-Order with Schema Migrations
Use something like Dapper or ADO.NET to perform data migrations based on the schema at the time the migration is written. You can get the
DbConnection object from the EF Context using
Pros: Migration code will never need to be changed
Cons: You won't get any of the benefits of EF Core
Perform Data Migrations After Schema Migrations
EF performs migrations in the ascending order of the
MigrationAttribute.Id string value. EF generates this based off a timestamp when calling
dotnet ef migrations add xxx. You can change this attribute to ensure Data Migrations are run after all Schema Migrations. Change the filename as well for readability so that they stay in the order they will be applied.
Pros: You get all the benefits of EF Core
Cons: If the schema changes in the future, such as removing a column referenced in the data migration, you will need to modify your migration
// change [Migration("20191002171530_DataMigration")] // to [Migration("99999999000001_DataMigration")]