Skip to content

Instantly share code, notes, and snippets.

@antontjea
Created October 5, 2012 16:26
Show Gist options
  • Save antontjea/3840829 to your computer and use it in GitHub Desktop.
Save antontjea/3840829 to your computer and use it in GitHub Desktop.
Entity Framework Test Database Initialiser
using Codeant.Samples.EntityFramework;
using Machine.Specifications;
namespace Codeant.Samples.Specs
{
public class AssemblyContext : IAssemblyContext
{
#region Implementation of IAssemblyContext
public void OnAssemblyStart()
{
TestDatabaseInitializerUtil.Initialize();
}
public void OnAssemblyComplete()
{
//Teardown is performed as part of OnAssemblyStart()
}
#endregion
}
}
using System.Data.Entity;
namespace Codeant.Samples.EntityFramework
{
public class DataContext : DbContext
{
public DbSet<User> Users { get; set; }
}
public class User
{
public string Username { get; set; }
}
}
using System;
using System.Data.Entity;
namespace Codeant.Samples.EntityFramework
{
public class TestDatabaseInitializer<TContext>
: IDatabaseInitializer<TContext> where TContext : DbContext
{
public TestDatabaseInitializer(Action<TContext> seed = null)
{
Seed = seed ?? delegate { };
}
public void InitializeDatabase(TContext context)
{
if (context.Database.Exists())
{
//If the data model and database schema match
if (context.Database.CompatibleWithModel(false))
{
//To speed things up no need to drop the database
context.Database.ExecuteSqlCommand(Sql.DisableConstraints);
context.Database.ExecuteSqlCommand(Sql.DeleteData);
context.Database.ExecuteSqlCommand(Sql.EnableConstraints);
context.Database.ExecuteSqlCommand(Sql.ReseedIdentities);
}
else //if the data model and database do NOT match
{
var databaseName = context.Database.Connection.Database;
//To close open connections set database to single user
//Thanks to http://stackoverflow.com/a/10745559
context.Database.ExecuteSqlCommand(
String.Format(Sql.SetDatabaseSingleUser, databaseName));
//Drop database
context.Database.ExecuteSqlCommand(
String.Format(Sql.DropDatabase, databaseName));
context.Database.Delete();
}
} //END if (context.Database.Exists())
//Create db if required
context.Database.CreateIfNotExists();
//Seed test data if any
Seed(context);
}
public Action<TContext> Seed { get; set; }
}
/// <summary>
/// Store of reusable sql statements
/// </summary>
public static class Sql
{
public const string DisableConstraints =
"EXEC sp_MSForEachTable 'ALTER TABLE ? NOCHECK CONSTRAINT all'";
public const string DeleteData =
"EXEC sp_MSForEachTable 'DELETE FROM ?'";
public const string EnableConstraints =
"EXEC sp_MSForEachTable 'ALTER TABLE ? WITH CHECK CHECK CONSTRAINT all'";
public const string ReseedIdentities =
"EXEC sp_MSForEachTable 'IF OBJECTPROPERTY(object_id(''?''), ''TableHasIdentity'') = 1 DBCC CHECKIDENT (''?'', RESEED, 0) '";
public const string SetDatabaseSingleUser =
"ALTER DATABASE {0} SET SINGLE_USER WITH ROLLBACK IMMEDIATE";
public const string DropDatabase =
"USE master DROP DATABASE {0}";
}
}
using System.Data.Entity;
namespace Codeant.Samples.EntityFramework
{
/// <summary>
/// Utility for initialising the test database
/// </summary>
public class TestDatabaseInitializerUtil
{
/// <summary>
/// Initialises the test database with test data.
/// </summary>
public static void Initialize()
{
//Replace DataContext with your implementation
Database.SetInitializer(
new TestDatabaseInitializer<DataContext>(Seed));
var context = new DataContext();
context.Database.Initialize(false);
}
/// <summary>
/// Seeds the test data.
/// </summary>
/// <param name="context">The context.</param>
internal static void Seed(DataContext context)
{
var testUser = new User { Username = "Test" };
context.Users.Add(testUser);
context.SaveChanges();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment