I had a “demo gods” problem recently…of course I hit the jackpot combo during a conference presentation though never while practicing.
Remember that EF7 is not EF6 with new features. So behavior can change and I didn’t check this one.
In EF6 if you have migrations and either let DbInitialization create the database or use Database.Create(), the database will get created along with the migrations in the MigrationHistory table.
With EF7 if you use EnsureCreated to create the database at runtime, as I had in some of my tests where I literally wanted to check behavior in the database, the migration history table DOES NOT GET CREATED.
This messed me up because I was demoing a migrations feature after having run one of these tests. With the migration history table wiped out by my test, the update-database command attempted to start with the very first migration, not the one I had just added in my demo. This caused a conflict because that migration was attempting to create a table that already existed in the database.
I couldn’t figure out what the problem was on the fly, so I moved on, with assurances to the attendees that I’d done a lot of work with migrations and new they worked as expected. And that a) it was a beta b) I would run it by the team and c) “you can trust me”.
So, blaming it on “beta” was not fair and it was not right. The blame lay between the chair and the keyboard, as they say. I hadn’t even run that test in my conference session yet. But I had re-run all fo the tests one last time right before I started the session, which put the database in this bad state.
Here, from one of EF7 issues raised on Github is Rowan Miller’s explanation:
EnsureCreated
totally bypasses migrations and just creates the schema for you, you can’t mix this with migrations.EnsureCreated
is designed for testing or rapid prototyping where you are ok with dropping and re-creating the database each time. If you are using migrations and want to have them automatically applied on app start, then you can usecontext.Database.Migrate()
instead.
So I’ve gone back to my tests and made sure the ones that use the database make use of the Migrate command.
My anticipated uses:
- EnsureCreated for on the fly DB creation on devices (e.g. phones)
- EnsureCreated for integration testing when I’m pointing to a unique testing-only database.
- Migrate for integration testing when my tests involve a test database that uses migrations. I think this will be rare and this is what I wanted for my conference demo.
- Migrate for, as Rowan suggests, Migrating a db on app startup. This could be for example, client apps (ala WPF) or web sites you’ve deployed to Azure.
Keep in mind that these demos where Migrate made more sense, are demos I am using to help people understand how EF7 works, not to demonstrate how to build tests when employing Entity Framework in your application. So some of the things I am doing are not necessarily how I would use tests when building software.