Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Entity Framework 4.1 "Code First" SetInitializer not being called again after Database.Delete

Trying to do some unit testing with EF 4.1 code first. I have my live db (SQL Server) and my unit test DB( Sql CE). After fighting (and losing) with EF, Sql CE 4.0 and Transaction support I decided the simplest way to run my test was to:

  1. Create Db
  2. Run Test
  3. Delete Db
  4. Rinse and repeat

I have my [Setup] and [TearDown] functions:

[SetUp]
public void Init()
{
    System.Data.Entity.Database.SetInitializer(new MyTestContextInitializer());
    _dbContext = ContainerFactory.Container.GetInstance<IContext>();
    _testConnection = _dbContext.ConnectionString;
}

[TearDown]
public void Cleanup()
{
    _dbContext.Dispose();
    System.Data.Entity.Database.Delete(_testConnection);
}

Issue is that System.Data.Entity.Database.SetInitializer does not call MyTestContextInitializer after the first test.

Hence the 2nd test then fails with:

System.Data.EntityException : The underlying provider failed on Open.
----> System.Data.SqlServerCe.SqlCeException : The database file cannot be found. Check the path to the database

TIA for any pointers

like image 882
ozczecho Avatar asked Mar 31 '11 00:03

ozczecho


3 Answers

I got around this by calling 'InitializeDatabase' manually. Like so:

   [SetUp]
    public void Init()
    {

        var initializer = new MyTestContextInitializer();
        System.Data.Entity.Database.SetInitializer(initializer);

        _dbContext = ContainerFactory.Container.GetInstance<IContext>();
        initializer.InitializeDatabase((MyTestContext)_dbContext);

        _testConnection = _dbContext.ConnectionString;
    }

    [TearDown]
    public void Cleanup()
    {
        System.Data.Entity.Database.Delete(_testConnection);

        _dbContext.Dispose();
    }

I think it may be a bug with EF 4.1 RC.

like image 80
ozczecho Avatar answered Sep 20 '22 10:09

ozczecho


It's not a bug, the initializer set with

System.Data.Entity.Database.SetInitializer

is only called when the context is created for the first time in the AppDomain. Hence, since you're running all your tests in a single AppDomain, it's only called when the first test is ran.

like image 40
juanagui Avatar answered Sep 19 '22 10:09

juanagui


It took me almost a day to find out what caused my strange unittest behaviour: the database connection stayed open or the database was not created with a every new test. I searched everywhere for the root of the cause: MSTest (no Admin rights or where working copies of files somehow deleted?), SQL Server Express/CE (login failure?), Unity (objects not disposed?) or Entity Framework (no proper database initialization?). It turned out to be EF. Thanks a lot for the answer!

like image 1
Vincent0268 Avatar answered Sep 20 '22 10:09

Vincent0268