Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Check if applied migrations match the DbContext?

I want to create a unit test to ensure no developer will commit model changes without the corresponding migration.

How do I test that the database matches the DbContext?

like image 587
Alexander Herold Avatar asked Nov 03 '17 08:11

Alexander Herold


People also ask

What is Migrationsassembly?

By default, the migrations assembly is the assembly containing the DbContext. Change your target project to the migrations project by using the Package Manager Console's Default project drop-down list, or by executing "dotnet ef" from the directory containing the migrations project.

How do I run an existing migration in Entity Framework?

You can do this by running the Enable-Migrations command in Package Manager Console. This command will create a folder in your solution called Migrations, and put a single class inside it called Configuration.

Should you use using with DbContext?

EF and EF Core DbContext types implement IDisposable . As such, best practice programming suggests that you should wrap them in a using() block (or new C# 8 using statement). Unfortunately, doing this, at least in web apps, is generally a bad idea.


2 Answers

You can leverage some of the lower-level Migrations components to do that:

var migrationsAssembly = db.GetService<IMigrationsAssembly>();
var differ = db.GetService<IMigrationsModelDiffer>();

var hasDifferences = differ.HasDifferences(
    migrationsAssembly.ModelSnapshot.Model,
    db.Model);

Assert.False(hasDifferences, "You forgot to add a migration!");
like image 98
bricelam Avatar answered Sep 29 '22 20:09

bricelam


Based on @bricelam's answer I created a generic method to test for applied migrations.

private static void ShouldMatchContext<T>()
  where T : DbContext
{
  using (var connection = new SqliteConnection("DataSource=:memory:"))
  {
    connection.Open();
    var builder = new DbContextOptionsBuilder<T>();
    var db = Activator.CreateInstance(typeof(T), builder.UseSqlite(connection).Options) as T;

    db.Database.EnsureCreated();

    var migrationsAssembly = db.GetService<IMigrationsAssembly>();
    var differ = db.GetService<IMigrationsModelDiffer>();

    bool hasDifferences = differ.HasDifferences(migrationsAssembly.ModelSnapshot?.Model, db.Model);

    Assert.False(hasDifferences);
  }
}
like image 43
Alexander Herold Avatar answered Sep 29 '22 20:09

Alexander Herold