Sunday, 23 April 2017

How to code Entity Framework programmable migrations

The internets are eerily quiet when it comes to running Entity Framework's through code, which is odd because Entity Framework's Code First migrations are extremely powerful and calling them (or rolling them back) through the code seems an obvious choice to someone like me, who prefers to reduce the amount of complexity for the poor IT people handling deployment.

(And for poor me, too, I'm very lazy and I like being able to just press a button to make magic happen.)

The most important quirk of running migrations programmatically that you'll need to know before we begin is that the DbMigrator class, for reasons unclear, requires the Entity Framework Configuration class but uses it in a way that's incompatible with the Update-Database and Add-Migration scripts, even after manually configuring the ContextType and ContextKey properties. We'll set those anyway for consistency, but no matter where you store your migrations and however diligently you inform the DbMigrator (the MigrationsDirectory property was ignored too) you're going to be stuck with automatic migrations. And while we're fiddling with the Configuration class, be sure to make the internal Configuration class public.

Automatic migrations ignore the explicit migration files and detect changes between the context's models and the database. As with the Update-Database script, the database will be created if it hasn't been already. It will not function reliably unless the AutomaticMigrationDataLossAllowed property is set to true, and you'll also need to update the OnModelCreating method of your context class to allow for database calls when the models are out of sync to give you a chance to run the migrations:





Migrating up and down

Using automatic migrations to update your database is great, but what do you do if you need to roll back? DbMigrator requires a migration name to update to, and unlike the case with explicit migrations, the migration name is not established by the developer but is unique to the database in question.

Fortunately, the DbMigrator includes the GetDatabaseMigrations method, which returns a list of applied migrations; so while you won't be able to roll back to a predefined named state, you will be able to roll back to a previously run migration. Here it is important to note that the order of the migrations returned is not guaranteed, but the names begin with a timestamp so they're not too difficult to sort.



So rolling back the first of that list is as simple as



Seeding

Seeding must be performed manually after calling DbMigrator.Update(). The Configuration class' Seed method is protected, so add the following wrapper method to your Configuration class



and call it once the migration is complete.

No comments:

Post a Comment

@mysql/xdevapi joy!

after hitting a wall last night with the existing node.js mysql packages, which for some reason have been years behind integrating with mysq...