EF 4.3 Beta1—released yesterday—integrates Code First Migrations into the EntityFramework NuGet package. Part of this integration means that databases created with Code First no longer include the EdmMetadata table. The databases are instead setup to work directly with Migrations making it easy to migrate the database in the future even if this need is not anticipated when the database is first created. But what exactly happens behind the scenes? And what is the update experience for databases that already contain EdmMetadata? This post goes into some detail to answer these questions.
As described in an earlier post, EdmMetadata was a simple way of determining if the Code First model had been changed since the database was created. However, it couldn’t be used to determine how the model used to create the database was different from the current model. This didn’t matter too much since there was no way to migrate the database from one version to the next. Now that Code First Migrations is available it is important that the model information stored in the database is can be used by Migrations to determine what has changed in the model so that the database can be migrated.
Creating new databases with EF 4.3
The Database.Create method is called when DbContext is used with the Code First approach to create a database. All of the initializers (except the new MigrateDatabaseToLatestVersion initializer) use this method to create a database when needed. In previous versions of EF this method called the ObjectContext.CreateDatabase method to both create the database and execute all the DDL needed to create tables, etc. The EdmMetadata entity would also be included in the Code First model so that the EdmMetadata table was created.
Starting we EF 4.3 Database.Create instead attempts to use Code First Migrations to create the database and perform DDL. Essentially, Database.Create performs an initial automatic migration for you. As part of this process Migrations will create a table called __MigrationHistory and insert a row into this table containing a compressed version of your Code First model. The database is thus setup to use Migrations in the future if you choose to do so.
(Note that the __MigrationHistory table is made a system table if possible. This means that to see it you may need to expand the “System Tables” in SQL Management Studio or your preferred tool.)
Currently Migrations cannot be used to create a database for you when not using Microsoft SQL Server or SQL Server Compact Edition. In these cases ObjectContext.CreateDatabase is still used and the __MigrationHistory table is then added using ObjectContext.CreateDatabaseScript. The result is essentially the same as if an automatic migration had been used.
Checking model compatibility
The CreateDatabaseIfNotExists and DropCreateDatabaseIfModelChanges initializers use the Database.CompatibleWithModel method to determine whether or not the Code First model matches the model that was used to create the database. This method would previously use the model hash stored in the EdmMetadata table. When the __MigrationHistory table is present CompatibleWithModel instead uses the Migrations model differ to determine compatibility. For the most part the results should be the same, although there is now less chance that CompatibleWithModel will produce false negatives where the hashes are different but the underlying model is fundamentally the same.
Upgrading existing EdmMetadata databases
So what happens if you have an existing database that already contains the EdmMetadata table? Well, as long as the database doesn’t get re-created then nothing happens. EF 4.3 still knows how to use the EdmMetadata table to check for model compatibility and will use this method if __MigrationHistory is not present. If the database is not found to be compatible with the current model, then the behavior is the same as it was with previous versions. That is, an exception may be thrown or the database may be dropped and re-created depending on which initializer is being used.
If the database is dropped and re-created, then it will no longer contain the EdmMetadata table because, as described above, Database.Create will instead use Migrations and create the __MigrationHistory table.
Can I keep using EdmMetadata?
EF now no longer ever includes the EdmMetadata entity in Code First models and it is not recommended that it be used. For this reason the EdmMetadata class and the IncludeMetadataConvention have been obsoleted in EF 4.3. That being said, they are still functional, and they could still be used with some work. However, if you do find the need to use them it would be great if you could let the EF team know since any scenario where EdmMetadata is still needed is something we would like to investigate.