Multiple Contexts per Database in EF6

In EF5, migrations is only able to manage a single user model (DbContext) per physical database instance. In EF6 Migrations will be able to deal with managing multiple models per physical database instance.


Formerly Known as ‘Multi-Tenant Migrations’

This feature was formerly referred to as Multi-Tenant Migrations. This named caused confusion because the feature does *not* enable using the same context multiple times in the same database. Instead, we are making the migrations table multi-tenant so that two distinct models can coexist in the same database.


There are two principal ways that multi-tenancy can be realized in EF6:

1. ContextKey

DbMigrationsConfiguration.ContextKey is a new Migrations configuration property in EF6. Its primary purpose is to allow the __MigrationHistory table to store metadata for more than a single model. To enable this, a corresponding column is being added to the history table thus making the table multi-tenant by ContextKey.

The default value for the ContextKey property is the fully-qualified type name of the parent DbMigrationsConfiguration (typically a user derived class). However, the actual value is arbitrary and can be user-specified in the standard way. I.e. In the constructor of the derived DbMigrationsConfiguration - Although, this should typically only happen before any migrations have been applied to a target database (otherwise the existing history rows will need to be updated to the new key value).

The DbContext Initializer infrastucture also uses the __MigrationHistory table to store model metadata. In this case, the default value of ContextKey becomes the fully-qualified derived DbContext type name. When "growing-up" from Initializers to Migrations, Migrations detects such initializer rows and automatically sets the ContextKey property to the existing value in the scaffolded DbMigrationsConfiguration.

1. Default Schema Propagation

DbModelBuilder.HasDefaultSchema is a new Code First API in EF6. Its purpose is to allow the default database schema for a Code First model to be configured in one place - Previously the Code First default schema was hard-coded to "dbo" and the only way to configure the schema to which a table belonged was via the ToTable API.

In EF6, the configured default schema will also affect the Migrations infrastructure, in particular, the Migrations history table (__MigrationHistory), which stores the Migrations version history for a given user model. In this way it will be possible to have multiple __MigrationHistory tables within a given physical database and thus support multi-tenancy via schema partitioning.

The default schema for a given model is free to change over the lifetime of the model. When Migrations detects a schema change, both user objects and the __MigrationHistory table are transferred to the new schema. However, for implementation reasons, transferring the __MigrationHistory table to a different schema can only occur using a code-based migration.

Enable-Migrations Enhancements

To better support migrating multiple models within a single Visual Studio project, a -MigrationsDirectory parameter is being added to the Enable-Migrations command in EF6. This parameter is analogous to the existing DbMigrationsConfiguration.MigrationsDirectory property and affects the following:

  • The name of the project directory containing the scaffolded DbMigrationsConfiguration (and any subsequently scaffolded code-based migrations files).
  • The namespace of the scaffolded DbMigrationsConfiguration i.e. matching the directory structure.
  • Sets the MigrationsDirectory property in the scaffolded DbMigrationsConfiguration to the provided value.

Last edited Jan 25, 2013 at 10:42 PM by RoMiller, version 6

Comments

IainDowns Apr 23, 2013 at 1:39 PM 
Is it possible to mark an entity so that it is NOT included in migrations.
Currently we are adding entities to an existing database - some reflect existing tables and some new ones - we don't want DBSets that reflect existing tables to be included in the migration script.

CFI Feb 28, 2013 at 7:27 AM 
I also cam across the problem illopis described and it does not work automatically for me (Alpha 2), but you can delete the "double definitions" after they are generated in the first migration and they will not be regenerated on each migration, but it would be nice to have that work automatically somehow...

chris_vickerson Feb 3, 2013 at 3:10 PM 
rowan,

Is there a usable and repeatable process to get around this issue in the current released version? Do we need to make a single developer the maintainer of EF?

illopis Jan 7, 2013 at 10:10 AM 
This is the feature we have higher expectations for in our company.

Just to add to the open discussion here, please note that the scenario covered by this feature should include DbContexts held in assemblies that are discovered through loose-coupling methods, such as MEF, and that include contracts.

For example, it happens to us that sometimes entity X is both a business entity and a MEF contract, so it is mapped by an assembly to table X, but another assembly either inherits or references entity X from another entity Y. Migrations on the second assembly should not contain the definition of entity X since that would mean double-defining table X, but should contain the reference and the foreign key specifications needed for enabling the relation between entity X and entity Y, so that modeled relations between both assemblies have their map to the database.

Rashun Nov 27, 2012 at 8:43 PM 
What is the recommendation for fully qualified namespaces (Tenant.Schema.TableName)? I believe Sql Server qualifier are ServerName.Owner.Schema.Table.

sunevnuahs Sep 18, 2012 at 12:33 PM 
Glad to see this arriving with EF6. Had previsouly managed to get a schema based migration working with custom sql and code generators.
Could get migrations working, but had to jump through a few hoops when it came to the __MigrationsHistory table and adding a new migration.
This will make life much easier - will be getting the code asap to test it.