Adrian Colquhoun
Adrian Colquhoun

Reputation: 51

EF 5.0 - Stop base class and subclasses being combined into a single database table when used in different DbSets

I have a code first DbContext which uses a base class and sub classes in different DBSets

eg. DbSet Animals; DbSet Dogs; DbSet Cats;

Where Dog and Cat are subclasses of animal. When the database is generated by code first EF 5.0 I only get one table (Animal) - where as I expected (and wanted three) - Animals, Cats & Dogs. Is there a way to make it do this (using the fluent api?)?

Upvotes: 3

Views: 2806

Answers (1)

Ladislav Mrnka
Ladislav Mrnka

Reputation: 364389

Yes there is a way to make it through fluent API but the mapping is dependent on the type of inheritance you are expecting. At the moment you have default Table-per-Hierarchy inheritance mapping where all entities are mapped to the same table with one additional column called by default Discriminator to differ among types stored in each record.

Suppose that you have these entities:

public class Animal {
    public int Id { get; set; }
    public string Name { get; set; }
}

public class Dog : Animal {
    public string Breed { get; set; }
}

Now if you use Table-per-Type inheritance mapping:

public class Context : DbContext {
    public DbSet<Animal> Animals { get; set; }
    public DbSet<Dog> Dogs { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder) {
        modelBuilder.Entity<Dog>().ToTable("Dogs");
    }
}

You will get two tables: Animals with Id and Name columns and Dogs with Id and Breed column. There will be also one-to-one relation between tables because each Dog entity has its record in both tables.

If you use Table-per-Class inheritance mapping:

public class Context : DbContext {
    public DbSet<Animal> Animals { get; set; }
    public DbSet<Dog> Dogs { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder) {
        modelBuilder.Entity<Dog>().Map(m => {
            m.MapInheritedProperties();
            m.ToTable("Dogs");
        });
    }
}

You will again get two tables. Animals will be the same as in the first case but Dogs will contain columns from both parent and child class: Id, Name, Breed. There will also be no relation between those entities because Dog will have all data in its own class.

TPC inheritance may seem better but it is much harder to use. For example EF don't use identity for Id because Id must be unique among all tables in TPC inheritance. Navigation properties in the base entity of TPC inheritance cause also issues.

Upvotes: 9

Related Questions