After migrating to Entity Framework 6 I get an error when executing unit tests on the build server.
I'm using the DropCreateDatabaseIfModelChanges
initializer. When I change it to MigrateDatabaseToLatestVersion
everything works, but I want to stick with the former initializer.
The error I'm getting is:
System.InvalidOperationException: System.InvalidOperationException:
The model backing the 'AppContext' context has changed since the
database was created. Consider using Code First Migrations to update
the database (http://go.microsoft.com/fwlink/?LinkId=238269)..
Which is correct, it changed, but with DropCreateDatabaseIfModelChanges
initializer, it should be recreated. Any ideas?
EF is configured in App.config. Here's the relevant part:
<connectionStrings>
<add name="AppContext" connectionString="Data Source=(localdb)\v11.0;Initial Catalog=my.app.unittest;Integrated Security=True" providerName="System.Data.SqlClient" />
</connectionStrings>
<entityFramework>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
<parameters>
<parameter value="v11.0" />
</parameters>
</defaultConnectionFactory>
<contexts>
<context type="my.app.core.Data.AppContext, my.app.core">
<databaseInitializer type="System.Data.Entity.DropCreateDatabaseIfModelChanges`1[[my.app.core.Data.AppContext, my.app.core]], EntityFramework" />
</context>
</contexts>
<providers>
<provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
</providers>
</entityFramework>
Best Answer
Well, it looks like EF 6.0 introduces a new rule:
"If the DbContext is using an Initializer AND Migrations are configured, throw an exception when building the model".
Up to and including the EF 6 RC this wasn't enforced. The annoying part is that "Migrations are configured" is defined by the implementation of a DbMigrationsConfiguration. There doesn't appear to be a way to programmatically disable Migrations in tests - if you implemented
I worked around it in a way very similar to Sebastian Piu - I had to get rid of the Configuration class from my tests, but I couldn't just remove it because we're using Migrations for our main project. Argh!
This was my code before:
I encountered the System.InvalidOperationException when the DbContext was being initialized in my test code. Since the application doesn't use any Initializer, there were no problems running the app as before. This only broke my tests.
The solution (which feels more like a workaround to things missing from EF) is to segment the Initializer and DbMigrationsConfiguration so only one is seen in a runtime environment. I want my tests to use the Initializer and I want my application to use the DbMigrationsConfiguration. This could be done more cleanly if DbContext had an interface, but alas it only implements IObjectContextAdapter.
First I made my DbContext abstract:
Then I derived 2 classes:
Both a MyDbContext and a MyTestDbContext are IMyDbContexts, so your existing dependency injection setup should work without requiring changes. I only tested Spring.NET.
My DbMigrationsConfiguration implements the derived type that is NOT used by tests:
Finally, the initializer's type was moved to the derived test class type:
I can confirm my tests are passing and my application (and Migrations) is still working as before.