Multiple DbContext Migrations with Inheritance and Relations and MEF

Topics: EF Runtime
Jan 7, 2013 at 11:35 AM

Hello.

This is my first post to CodePlex, so if I make any mistake by posting here please be indulgent.

We're actively using EF 4.3 (wich is virtually the same as EF5 but for .Net 4.0) with CodeFirst and Migrations on an MVC4 Web API application that is very modularized and loose coupled through MEF and contracts.

Each Web API module is discovered at run-time and the Migrations held by each of the modules is executed when discovered. Some of these modules interact with each other, defining contracts that are either inherited or referenced by other assemblies' entities.

When creating a migration on DbContext A, that references entity B from a foreign contract assembly, this migration by default tries to create entity B table too. However, since this entity is defined in a foreign (but not referenced at compile-time) assembly, there is no need for creating table B. This table is only created if assembly B is found.

Today we manually remove all code from external assemblies off the migrations generated by the "add-migration" method on these assemblies because there is no possibility of removing them from the DbModelBuilder or the Configuration. We keep however the creation of tables and foreign keys, since they must be created for relations or inheritance to work correctly.

It would be a good thing to be able to mark some entities as "Externally managed" so that tables or foreign keys that relate to these are only created if no table or foreign key is already found in the database.

 

This is an example:

// Contracts.dll
public class EntityA
{
    public int Key { get; set; }
}

// AssemblyA.dll
public class ContextA : DbContext
{
    DbSet<EntityA> AEntities { get; set; }
    // When migrations for ContextA are generated, table EntityA is
    // automatically created
}

// AssemblyB.dll
public class EntityB : Contracts.EntityA
{
    public virtual ICollection<EntityA> AEntities { get; set; }
}

public class ContextB : DbContext
{
    DbSet<EntityB> BEntities { get; set; }
    // Migrations for ContextB also contain the definition to create
    // table EntityA, but this is already generated by migrations in
    // AssemblyA.dll migrations, so there is an exception thrown
}

// It could be solved with some code like this
public class ContextB : DbContext
{
    /// ...
    public override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Configurations.Entity<EntityA>().IsExternal();
    }
    /// ...
}

Jun 24, 2013 at 3:11 PM
Hello,

is there any solution to this problem?

Thank you!

Dusan