Tallan's Technology Blog

Tallan's Top Technologists Share Their Thoughts on Today's Technology Challenges

Entity Framework 7 Migrations and Source Control

Nick Rubino

When I first came across migrations in Entity Framework 6 I thought it was a fantastic way to track data model changes in a project.  This thought lasted until my team started to share and sync these migrations through source control.  Anyone that has attempted to use migrations on a development team will agree that it is very cumbersome to sync database changes across development environments.  Searching “on the line” for difficulties in using migrations on a team, you quickly find links to pages such as this, an MSDN article about how hard syncing EF migrations really are.  Most of the issues with EF6 migrations are due to the dependence on the __EFMigrationsHistory table EF6 creates and uses when creating migrations.  Since there was no easy way for devs to share this table, if two devs made changes since the most recent checkin there would mismatching entries in this table across their environments, and the EF6 migration tool would throw a fit when trying to sync.

Long story short my team dumped the idea of migrations and used a less elegant method; when data model changes were necessary, we rebuilt the database, schema compared it to the previous version to generate an update script that we ran on dev/qa/prod environments to update the database to the newest model.

With Entity Framework 7 RC1 being released earlier this year I have read (a post by Julie Lerman the EF guru) that the migrations tool has changed and now is far less reliant on the __EFMigrationsHistory table generating code that can be synced in source control without the hassle involved in EF6.  I have created this blog post to see how true this actually is.  I will be creating a simple EF7 project with a small data model, will then mimic the act of two different developers making two different data model changes on their local instances, and then see how easy it really is to sync these changes in git.

Step 1 – I created the initial development environment (DE1) and data model.

Two tables; Album and Artist below.

public class Album
{
  public int AlbumId { get; set; }
  public string Name { get; set; }
  public Artist Artist { get; set; }
  public int ArtistId { get; set; }
}

public class Artist
{
  public virtual int ArtistId { get; set; }
  public virtual string FirstName { get; set; }
  public virtual string LastName { get; set;}
  public virtual List<Album> Albums { get; set; }
}

I ran Add-Migration from the console and it generated the following migration files.

Step1SolutionExporer

I then pushed/synced the code to GIT.

Step 2 – I created a separate development environment (DE2) by cloning the git repo into a different folder and made datamodel changes to this code.

Added a Song object to the datamodel so that the objects in DE2 looked like this:

public class Album
{
  public int AlbumId { get; set; }
  public string Name { get; set; }
  public Artist Artist { get; set; }
  public int ArtistId { get; set; }
  public List<Song> Songs {get;set;}
}

public class Artist
{
  public virtual int ArtistId { get; set; }
  public virtual string FirstName { get; set; }
  public virtual string LastName { get; set;}
  public virtual List<Album> Albums { get; set; }
}

public class Song
{
  public int SongId { get; set; }
  public Album Album { get; set; }
  public int AlbumId { get; set; }
}

I ran “Add-Migration CreateSong” from the console, it added a new migration file and modified the snapshot file as can be seen in the following image.

Step2SolutionExporer

I pushed/synced the code to GIT.

Step 3 – In development environment 1 (DE1), without syncing with GIT, I will make different data model changes.

I added a RecordLabel object to the datamodel so that the objects in DE1 looked like this:

public class Album
{
  public int AlbumId { get; set; }
  public string Name { get; set; }
  public Artist Artist { get; set; }
  public int ArtistId { get; set; }
  public RecordLabel RecordLabel { get; set; }
  public int RecordLabelId { get; set; }
}

public class Artist
{
  public virtual int ArtistId { get; set; }
  public virtual string FirstName { get; set; }
  public virtual string LastName { get; set;}
  public virtual List<Album> Albums { get; set; }
}

public class RecordLabel
{
  public int RecordLabelId { get; set; }
  public List<Album> Albums { get; set; }
}

I ran “Add-Migration CreateRecordLabel” from the console, it added a new migration file and modified the snapshot file as can be seen in the following image.

Step3SolutionExporer

I committed DE1, pulled the DE2 code from GIT and BOOM CONFLICTS!  I have never in my life been this excited to merge conflict.

Step 4 – I will resolve the conflicts and make sure the database builds correctly.

There were 3 conflicts as can be seen in the following image.

Step4MergeConflicts

The merge for the EF7TeamMigrations.csproj and Album.cs files in the conflict list above will not be explained because they are unrelated to entity framework migrations.  The diff for the MusicContextModelSnapshot.cs file can be seen in the following image.

Step4Diff

As expected the addition of the Song object on DE2 is conflicting with the addition of the RecordLabel object on DE1.  I merged the conflicting line in the file manually as can be seen in the following image.

Step4Merge

The other two conflicted files we merged without issues, I ran an Update-Database command and my local database had both the Song table and RecordLabel table with all relationships as expect.  Success!

I pushed my merged changes to GIT.

Conclusion

As I had hoped EF7 migrations are exponentially more intuitive to work with in a team environment with source control.  Using migrations will benefit many teams so that it is easier to track, update, and rollback datamodel changes between migrations using the tools included with EntityFramework.Commands nuget package.  I am looking forward to using EF7 migrations with my next project. I am hoping this write up will help anyone looking into using EF7 migrations in a code first project.

You can view and drill into all changes outlined above here at the GIT repo I created for this experiment.

No comments

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

\\\