I'm investigating using Code-Based EF Migrations for a product that does not use EF. Everything generally works well, except that the command:
Add-Migration MyTestMigration
outputs the following message:
Unable to generate an explicit migration because the following explicit migrations are pending: [201206260845338_DannyTest]. Apply the pending explicit migrations before attempting to generate a new explicit migration.
The reason for this is that the connection string is not known at build time, and EF has randomly created a database called "MyContextName" on .SQLExpress. I cannot apply the pending migration, because it references database tables that do not exist in this database - we're just trying to use migrations as a way of executing our scripts;
So the questions are:
If we're not using Automatic Migrations (we have EnableAutomaticMigrations=false), why does Add-Migration
require that the database is up-to-date even though it has absolutely no impact on the generated (empty) migration? I find it hard to believe MS don't intend this use case when so much of it works; the only "broken" thing is validation that doesn't affect any behaviour.
Is there any way around this other than creating our own Add-Migration command that just duplicates what the EF one does, but skips the (seemingly needless) DB up-to-date check? I've tried passing various arguments, but so far not managed to make it work.
Edit:
I actually found a better way to solve this problem, but it's not really an answer to these questions, so adding it here. Hopefully will get time to turn this into a blog post!
The only reason I wanted to use Add-Migration was because of all the guff that went along with the DbMigration; but I realised that with a base class, we could basically eliminate the need for all this by having the base class auto-generate the migration ID from an attribute. The Target is identical for all our migrations, as the model state doesn't change. Now, we just manually create our migrations like this (the date is required to build the ID such that EF will apply them in the correct order):
[Migration(2012, 6, 27, 12, 00, "Add new xxx fields for yyy")]
internal class MyNewMigration : MyDbMigration
{
public override Up()
{
// ...
}
public override Down()
{
// ...
}
}
The MyDbMigration
class has the Target/Source/Id properties. Target is hard-coded (the same value that Add-Migration created with the first migration), Source is null, and Id is some reflection that reads the MigrationAttribute. This means we can now just manually create these classes; which isn't a lot of effort now we don't have to worry about all the IMigrationMetadata stuff :-)
See Question&Answers more detail:
os 与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…