I have project with code first migrations. And I was stuck in situation, when Add-Migration throws an Exception. So I decided to use it with -IgnoreChanges and write migration code myself.
Now I want to check whether the database after the custom migration is compatible with the model. All I found is CompatibleWithModel method, but it compares the model with the schema stored in the __MigrationHistory table, and not with the schema of the database itself, so in my case it is useless.
EF 6.1.3
Related
I have a .net core 2 project, along with Entity framework Core.
I have an existing database, and I've mapped them out to database entities in code.
The problem is that when I add a migration, expectedly it picks up my entity as a new table, however it is an existing table. The table shares the same name.
I suppose, I could just remove the contents of the Up method of the migration, but I want to know if there is a proper way instead of a workaround.
So, what I am asking is how can I tell entity framework core that this table is already existing?
EF 6 had an -IgnoreChanges option that would just take a snapshot with no Up() code, but that feature is not in EF Core (yet). See here.
If you comment out the Up() code as you have suggested that will indeed capture a snapshot of your existing objects and subsequent migrations will be incremental.
We want to support all of the following scenarios using a EF6 database initializer to create or update an existing database from our EF6 model:
Create and initialize a new database.
Update an existing (legacy) database that has no __MigrationHistory table yet.
Update an existing (migrated) database that already has a __MigrationHistory table.
When using the CreateDatabaseIfNotExists database initializer, it covers only the first scenario. But then we cannot further evolve our data model.
When using the MigrateDatabaseToLatestVersion database initializer with an InitialDatabase migration that creates the base line database, we can support scenario 1 and 3. But it fails to upgrade existing legacy databases because the generated SQL statements are not idempotent. They fail e. g. with a "Table 'xy' already exists" error.
When using the MigrateDatabaseToLatestVersion database initializer with an empty InitialDatabase migration (=empty Up() method body), then we can only support scenario 2 and 3, but we cannot create new database from scratch.
I am looking for a way that combines the best of both worlds and supports all three required scenarios. Unfortunately this seems impossible with the current EF6 design. The problem I am facing is that the DbMigration steps are discovered using reflection and there seems to be no (clean) way to intercept this. What I would like to do is to write an enhanced "hybrid" database initializer that:
1. Checks if the database exists.
2. If not, then execute all migrations (=default behavior of MigrateDatabaseToLatestVersion).
3. Otherwise check if it is already enabled for migrations (i. e. table __MigrationHistory exists).
4. If yes, then execute only the pending migrations (=default behavior of MigrateDatabaseToLatestVersion).
5. Otherwise execute all DbMigrations except the very first "InitialDatabase" migration. This should also create the __MigrationHistory table and include all(!) migrations (including the very first "InitialDatabase" migration).
I don't find a way to implement step 5.
I would be happy with a "hack" that lets me just catch and ignore exceptions from upgrade operations of the first step (with a well-known MigrationId). I already thought about deriving a class from DbMigrator and override the ApplyMigration method with a
try
{
base.ApplyMigration(...)
}
catch
{
...ignore if migrationMetadata.Id=="my well-known id"..
}
block. But this is impossible because the ApplyMigration is internal.
Any ideas on this?
I've set up this project from DB first and everything went fine. I can debug properly. But when I try make a change to one of my models, instead of the new migration showing a simple AlterColumn statement, it keeps trying to reinitialize the entire database.
I've tried running update database -script and only inserting the _MigrationHistory table record. Even after that, it still wants to create all the tables.
Has this ever happened to anyone?
When you start with an existing database you need to do an empty (no-op) migration to set a baseline. This is because EF will use the model in the prior migration to compare, so if there is not one (in code) you get all your database objects. Inserting a record into __MigrationHistory just tells EF the code migration has been applied - it doesn't use it for the compare.
enable-migrations
add-migration MyBaseline -IgnoreChanges // no Up() code, but model saved
update-database
// Now I can change my model and generate a migration with difference
See here.
I'm using an existing database and I have mapped one of the tables as an entity (as i needed to map a foreign key).
So when it comes to initialising this database I would like EF to ignore this entity since it already exists.
How would I go about doing this?
You should create an empty migration as the first migration with the -IgnoreChanges flag to allow Entity Framework to get a snapshot of the existing database.
So out of the gate use:
Add-Migration InitialMigration -IgnoreChanges
and that will create a blank migration but it will update the Entity Framework metadata allowing the existing tables to exist and not be touched by migrations.
Also to be mentioned that the naming conventions that Entity Framework expects and your database schema may differ. You may need to manually setup the foreign keys using the Fluent API.
I didnt check with EF 6 specifically, but I think default EF behavious is that when the database exists, then it presume all model be ready and therefore will create no tables. If you want your initialization code to create tables with code first, use initialization code for prepare data. Look here :
http://www.entityframeworktutorial.net/code-first/seed-database-in-code-first.aspx
I have a situation where I need to make changes to my Model (code-first) and mirror the changes manually on the database. Migrations are not an option. Unfortunately, this causes entity framework to throw an exception when it validates the schema against the model (using the __MigrationHistory table). Is there a way to disable the schema validation that entity framework does? I'm using EF 4.3 specifically.
I would imagine you could create your own implementation of IDatabaseInitializer that does nothing, and use Database.SetInitializer().