I hope I understand the basic workflow. First I create a model, then I generate an initial migration, and I generate an SQL from that, OK. I update the model, I create a new migration from that, and a new SQL from that, OK.
Am I correct in assuming that this is a one-way only workflow? If I change the migration class in a bad way, it will not ever be reflected in my model, and if the database schema is not exactly what it should be, EF will never notice, and I will only get weird exceptions, right?
How to be sure that when I modify a migration class, I do not cause inconsistencies? I assume I can only do two things: first, add new database objects which EF doesn't care about, second, change EF-generated migration code in a way that it ends up with the same schema (for example, if EF generates a drop column
and an add column
, I can change that to a rename column
), and the Down()
and Up()
methods have to be consistent, is that all? For example, can I ever change the schema that EF cares about?
EF Core compares the current model against a snapshot of the old model to determine the differences, and generates migration source files; the files can be tracked in your project's source control like any other source file. Once a new migration has been generated, it can be applied to a database in various ways.
Definitely the migrations should be committed in source control. Deleting migrations will make it impossible for EF to generate future migrations for future changes to an existing database.
Hi @PanagiotisKanavos, as you mentioned, it does not require migration.
Remove a migrationTo remove the last migration, use this command. After removing the migration, you can make the additional model changes and add it again. Avoid removing any migrations which have already been applied to production databases.
NOTE: I'll call "added-migration" to every migration created with Add-Migration
, or automatically created by automatic migrations
NOTE: when I say "state of DbContext" I mean the definition of the model done in code first, i.e. the entities, their properties, relations and all other configuration
NOTE: "known by the DbContext" means all kind of database objects which the DbContext is aware of, like tables or views mapped to entities. There are a lot of other things in the DB that the DbContext is not aware of, including tables and views not mapped to DbContext entities
I hope I understand the basic workflow. First I create a model, then I generate an initial migration, and I generate an SQL from that, OK. I update the model, I create a new migration from that, and a new SQL from that, OK.
Of course, and you can change the DB schema from one added-migration to other added-migration, no matter if it's an upgrade or downgrade, or how many added-migrations are in between. I.e. you can specify source and target migrations.
Am I correct in assuming that this is a one-way only workflow?
If this means that you can only apply migrations from code to DB, yes, it's only from code to DB, and no the other way.
If I change the migration class in a bad way, it will not ever be reflected in my model,
Why would you do so? Migrations have been created just for doing it flawlessly without making mistakes. Why doing it by hand? An added-migration includes the definition of the process to upgrade from the DbContext state of a previously added-migration to the current DbContext state. And the process to downgrade, i.e. to go back to the DbContext state of a previously added-migration. If you're not careful when modifying the migrations, you can break this.
and if the database schema is not exactly what it should be, EF will never notice, and I will only get weird exceptions, right?
Nope! it has nothing to do with migrations. Independently of migrations, when a DbContext is instanced, the model is created in memory, and checked against the DB schema. If it doesn't match, you'll get an exception. But this has nothing to do with migrations.
You usually modify your model, add a migration, and apply the migration to the DB, so that the DbContext and the DB schema are synchronized. Other option is to modify the DB and use a T4 template to reverse engineer the DB and obtain a DbContext from the DB schema. The question is that both must be synched, but it doesn't matter how you do it.
How to be sure that when I modify a migration class, I do not cause inconsistencies? I assume I can only do two things: first, add new database objects which EF doesn't care about, second, change EF-generated migration code in a way that it ends up with the same schema (for example, if EF generates a drop column and an add column, I can change that to a rename column), and the Down() and Up() methods have to be consistent, is that all? For example, can I ever change the schema that EF cares about?
Don't mix up DB schema, DbContext and migrations concepts.
As stated above, DB and DbContext must be synchronized.
An migrations are an easy way to achieve this synchronization: you create the initial model and add the first added-migration. Then you create the DB. The DbContext and the DB schema are perfectly synchronized. What would happen if you modified the migration in a way that the DB schema changed and didn't match the DbContext? Your DbContext and your DB schema would be different, and an exception would be thrown when instancing the DbContext.
But then, why is there a migrations table on the DB?
When you apply a migration to the DB, the schema of the DB is updated, and an snapshot of the current schema (more precisely, of the part of the schema "known" by the DbContext, not of the whole DB Schema) is taken, and stored in the Model
column of __MigrationHistory
table in the database.
Migrations knows how to change the DB schema from a "source" added-migration to a "target" added-migration. The migration history table is used to verify that the DB schema is consistent with the last applied migration. I.e. before applying a new migration, migrations verifies that he current DB schema matches the schema when the last migration was applied by using the snapshot stored in the migrations table. If it doesn't match, the process will fail. If it matches, the migration will safely apply the changes from the "source" added-migration to the "target" added-migration, and store the snapshot of the resulting schema.
So, how can you break things?
What can be done safely?
Anything that doesn't change the schema of the DB "known" by the DbContext, i.e:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With