1

I have a table in an existing database that looks something like this:

PK
FK
Col1
Col2
Col3
Col4
Col5

I need to get it into a class hierarchy like this:

public abstract class BaseClass : Entity
{
    public int PK {get; set;}
    public string Col1 {get; set;}
}

public class Child1 : BaseClass
{
    public string Col2 {get; set;}
    public string Col3 {get; set;}
}

public class Child2 : BaseClass
{
    public string Col4 {get; set;}
    public string Col5 {get; set;}
}

I am currently using the Fluent API to configure the entities like so:

public abstract class BaseClassConfig<TEntity> : EntityTypeConfiguration<TEntity> where TEntity : Entity
{
    public BaseClassConfig()
    {
        ToTable("TheTableName");
        HasKey(x => x.Id);

        Property(x => x.Col1).HasColumnName("SomeName");
    }
}

public class Child1Config : BaseClassConfig<Child1>
{
    public Child1Config()
    {
        Property(x => x.Col2).HasColumnName("SomeName");
        Property(x => x.Col3).HasColumnName("SomeName");
    }
}

public class Child2Config : BaseClassConfig<Child2>
{
    public Child2Config()
    {
        Property(x => x.Col4).HasColumnName("SomeName");
        Property(x => x.Col5).HasColumnName("SomeName");
    }
}

When I added these to the context the inherits from DbContext:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Configurations.Add(new Child1Config());
    modelBuilder.Configurations.Add(new Child2Config());
}

I get the following error:

The entity types 'Child1' and 'Child2' cannot share table 'TheTableName' because they are not in the same type hierarchy or do not have a valid one to one foreign key relationship with matching primary keys between them.

I had a look at this article: http://www.asp.net/mvc/overview/getting-started/getting-started-with-ef-using-mvc/implementing-inheritance-with-the-entity-framework-in-an-asp-net-mvc-application

But it does not really talk about using the fluent api to configure the types, rather directly adding them to the context via DbSet<>.

How do I setup a single table to map to different classes through a base class using the fluent api?

3
  • Why are you splitting the entity class to three classes? Also as you defined the table name in abstract BaseClassConfig and implement it in two other ChildConfig classes, which is not clarifying actual Entity to be mapped in database. How you are calling these configuration? If you want the table structure then child2 class should inherit from child 1 and move ToTableName call to Child2Config Commented Aug 18, 2015 at 23:37
  • @SandeepKumar - Because the BaseClass has common properties to both Child1 and Child2, whereas each of them have their own properties not related to each other. It is inheritance in the simplest form. But in this case the existing schema has all the properties stored in the same table. Commented Aug 18, 2015 at 23:45
  • For EF, entitiies should be mapped to database tables. The purpose of EF code first is associating entity is to database table and entities should be uses for this purpose only. If you are intend to do something with this class hierarchy then first you create a simple entity for table and after that you have to create other classes (like DTOs) with this hierarchy and use them in your application. Use automapper or create mapping methods for processing your request from DTOs to Entity. This will transfer your application specific responsibility from entities to DTOs. Commented Aug 19, 2015 at 0:01

1 Answer 1

2

A good reference I turn to a lot is this MSDN article: Configuring/Mapping Properties and Types with the Fluent API

In it you'll see a reference to the Table-Per-Hierarchy (TPH) Inheritance pattern. Essentially what you are missing is a discriminator field (and based on the error, the FK is also not mapped).

By default, the discriminator column is called Discriminator, but as you can see from the article, this can be customized in the code-first mapping:

modelBuilder.Entity<Course>()  
    .Map<Course>(m => m.Requires("Type").HasValue("Course"))  
    .Map<OnsiteCourse>(m => m.Requires("Type").HasValue("OnsiteCourse"));

In the above example, Type is the discriminator which allows EF to know which entity type to materialize i.e. entity Course when Type == "Course".

Sign up to request clarification or add additional context in comments.

3 Comments

OK, but how do I use the fluent api to describe the properties on Child2 to EF? Is it not a good idea to use an inheritance pattern for fluent configurations?
I wouldn't try to use inheritance for the mapping configs. By convention the properties will be mapped correctly, but should you need to customize it, you can do in the Map lambda of each derived type. See if the answer here helps further: stackoverflow.com/questions/23366489/…
Pointed me in the right direction and your answer helped me as well. Thanks a bunch! But one more question, how do you mark derived type properties required in the fluent api? I noticed the Property() function is different inside the map function.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.