EF Migrations series
- Using Entity Framework to Create a Database
- Adding Indexes with EF Migrations
- Updating a Table with EF Migrations
- Indexes in Code-Based EF Migrations
- EF Migrations and a Merge Conflict
- Prevent EF Migrations from Creating or Changing the Database
- EF Code First Change Tracking
- EF Migrations Command Reference
- EF Code First Navigation Properties and Foreign Keys
- Update-Database MSI Custom Action
One of the features of Entity Framework Code First is to automatically create the database on first access. It is a convenient approach in many cases. Unfortunately the applications I work with does not fall into one of those cases. The applications I develop typically run on a dedicated web server, with the database hosted on in a shared MSSQL environment somewhere nearby.
The shared MSSQL environment is often set up using advanced clustering and virtualization technologies to maximise performance and reliability. In such an enviromnent my code seldom have access rights enough to create a database and even if it did, automatically created databases is not an option. Databases should be created by a DBA that carefully chooses the right name of the database, the right place for data and transaction log files and applies the right growth settings for the files.
To work with the shared MSSQL environment the application shouldn’t to any automatic creation or updates to the database schema. On startup I only want the application to check two things:
- that the database exists
- that the database is compatible with the model in the code.
Only after those checks have passed I want the application to run. A custom database initalization strategy can do those checks and throw exceptions that prevent the application from running if there is no existing and compatible database.
The ValidateDatabase Strategy
I’ve created a custom database initializer strategy that only does the validation steps and never creates or updates the database.
public class ValidateDatabase<TContext> : IDatabaseInitializer<TContext> where TContext : DbContext { public void InitializeDatabase(TContext context) { using (new TransactionScope(TransactionScopeOption.Suppress)) { if (!context.Database.Exists()) { throw new ConfigurationException( "Database does not exist"); } else { if (!context.Database.CompatibleWithModel(true)) { throw new InvalidOperationException( "The database is not compatible with the entity model."); } } } } } |
The strategy has to be set as the database context’s initialization strategy before the first database access. A static constructor of the context is guaranteed to run before the first use of the context, regardless of where in the application the context is first used.
static CarsContext() { Database.SetInitializer(new ValidateDatabase<CarsContext>()); } |
The auto creation and migration feature of the database is now effectively disabled. There is no risk for automatic changes being applied to a database server by mistake. The application will only use the database after it is verified to be compatible with the code.
awesome,well done.
According to the past entailed I would like to add this does not work for EF6
http://stackoverflow.com/questions/9703810/how-to-disable-migration-in-entity-framework-4-3-1
see that post.