Inheritance with EF Code First: Part 1 – Table per Hierarchy (TPH)

A simple strategy for mapping classes to database tables might be “one table for every entity persistent class.” This approach sounds simple enough and, indeed, works well until we encounter inheritance. Inheritance is such a visible structural mismatch between the object-oriented and relational worlds because object-oriented systems model both “is a” and “has a” relationships. SQL-based models provide only "has a" relationships between entities; SQL database management systems don’t support type inheritance—and even when it’s available, it’s usually proprietary or incomplete.

There are three different approaches to representing an inheritance hierarchy:
  • Table per Hierarchy (TPH): Enable polymorphism by denormalizing the SQL schema, and utilize a type discriminator column that holds type information.
  • Table per Type (TPT): Represent "is a" (inheritance) relationships as "has a" (foreign key) relationships.
  • Table per Concrete class (TPC): Discard polymorphism and inheritance relationships completely from the SQL schema.
I will explain each of these strategies in a series of posts and this one is dedicated to TPH. In this series we'll deeply dig into each of these strategies and will learn about "why" to choose them as well as "how" to implement them. Hopefully it will give you a better idea about which strategy to choose in a particular scenario.

Inheritance Mapping with Entity Framework Code First

All of the inheritance mapping strategies that we discuss in this series will be implemented by EF Code First CTP5. The CTP5 build of the new EF Code First library has been released by ADO.NET team earlier this month. EF Code-First enables a pretty powerful code-centric development workflow for working with data. I’m a big fan of the EF Code First approach, and I’m pretty excited about a lot of productivity and power that it brings. When it comes to inheritance mapping, not only Code First fully supports all the strategies but also gives you ultimate flexibility to work with domain models that involves inheritance. The fluent API for inheritance mapping in CTP5 has been improved a lot and now it's more intuitive and concise in compare to CTP4.

A Note For Those Who Follow Other Entity Framework Approaches

If you are following EF's "Database First" or "Model First" approaches, I still recommend to read this series since although the implementation is Code First specific but the explanations around each of the strategies is perfectly applied to all approaches be it Code First or others.

A Note For Those Who are New to Entity Framework and Code-First

If you choose to learn EF you've chosen well. If you choose to learn EF with Code First you've done even better. To get started, you can find a great walkthrough by Scott Guthrie here and another one by ADO.NET team here. In this post, I assume you already setup your machine to do Code First development and also that you are familiar with Code First fundamentals and basic concepts. You might also want to check out my other posts on EF Code First like Complex Types and Shared Primary Key Associations.

A Top Down Development Scenario

These posts take a top-down approach; it assumes that you’re starting with a domain model and trying to derive a new SQL schema. Therefore, we start with an existing domain model, implement it in C# and then let Code First create the database schema for us. However, the mapping strategies described are just as relevant if you’re working bottom up, starting with existing database tables. I’ll show some tricks along the way that help you dealing with nonperfect table layouts.

The Domain Model

In our domain model, we have a BillingDetail base class which is abstract (note the italic font on the UML class diagram below). We do allow various billing types and represent them as subclasses of BillingDetail class. As for now, we support CreditCard and BankAccount:

Implement the Object Model with Code First

As always, we start with the POCO classes. Note that in our DbContext, I only define one DbSet for the base class which is BillingDetail. Code First will find the other classes in the hierarchy based on Reachability Convention.
public abstract class BillingDetail 
{
    public int BillingDetailId { getset; }
    public string Owner { getset; }        
    public string Number { getset; }
}
 
public class BankAccount : BillingDetail
{
    public string BankName { getset; }
    public string Swift { getset; }
}
 
public class CreditCard : BillingDetail
{
    public int CardType { getset; }                
    public string ExpiryMonth { getset; }
    public string ExpiryYear { getset; }
}
 
public class InheritanceMappingContext : DbContext
{
    public DbSet<BillingDetail> BillingDetails { getset; }
}
This object model is all that is needed to enable inheritance with Code First. If you put this in your application you would be able to immediately start working with the database and do CRUD operations. Before going into details about how EF Code First maps this object model to the database, we need to learn about one of the core concepts of inheritance mapping: polymorphic and non-polymorphic queries.

Polymorphic Queries

LINQ to Entities and EntitySQL, as object-oriented query languages, both support polymorphic queries—that is, queries for instances of a class and all instances of its subclasses, respectively. For example, consider the following query:
IQueryable<BillingDetail> linqQuery = from b in context.BillingDetails select b;
List<BillingDetail> billingDetails = linqQuery.ToList();
Or the same query in EntitySQL:
string eSqlQuery = @"SELECT VAlUE b FROM BillingDetails AS b";
ObjectContext objectContext = ((IObjectContextAdapter)context).ObjectContext;
ObjectQuery<BillingDetail> objectQuery = objectContext.CreateQuery<BillingDetail>(eSqlQuery);
List<BillingDetail> billingDetails = objectQuery.ToList();
linqQuery and eSqlQuery are both polymorphic and return a list of objects of the type BillingDetail, which is an abstract class but the actual concrete objects in the list are of the subtypes of BillingDetail: CreditCard and BankAccount.

Non-polymorphic Queries

All LINQ to Entities and EntitySQL queries are polymorphic which return not only instances of the specific entity class to which it refers, but all subclasses of that class as well. On the other hand, Non-polymorphic queries are queries whose polymorphism is restricted and only returns instances of a particular subclass. In LINQ to Entities, this can be specified by using OfType<T>() Method. For example, the following query returns only instances of BankAccount:
IQueryable<BankAccount> query = from b in context.BillingDetails.OfType<BankAccount>() 
                                select b;
EntitySQL has OFTYPE operator that does the same thing:
string eSqlQuery = @"SELECT VAlUE b FROM OFTYPE(BillingDetails, Model.BankAccount) AS b";
In fact, the above query with OFTYPE operator is a short form of the following query expression that uses TREAT and IS OF operators:
string eSqlQuery = @"SELECT VAlUE TREAT(b as Model.BankAccount) 
                     FROM BillingDetails AS b 
                     WHERE b IS OF(Model.BankAccount)";
(Note that in the above query, Model.BankAccount is the fully qualified name for BankAccount class. You need to change "Model" with your own namespace name.)

Table per Hierarchy (TPH)

An entire class hierarchy can be mapped to a single table. This table includes columns for all properties of all classes in the hierarchy. The concrete subclass represented by a particular row is identified by the value of a type discriminator column. You don’t have to do anything special in Code First to enable TPH. It's the default inheritance mapping strategy:
This mapping strategy is a winner in terms of both performance and simplicity. It’s the best-performing way to represent polymorphism—both polymorphic and nonpolymorphic queries perform well—and it’s even easy to implement by hand. Ad-hoc reporting is possible without complex joins or unions. Schema evolution is straightforward.

Discriminator Column

As you can see in the DB schema above, Code First has to add a special column to distinguish between persistent classes: the discriminator. This isn’t a property of the persistent class in our object model; it’s used internally by EF Code First. By default, the column name is "Discriminator", and its type is string. The values defaults to the persistent class names —in this case, “BankAccount” or “CreditCard”. EF Code First automatically sets and retrieves the discriminator values.

TPH Requires Properties in SubClasses to be Nullable in the Database

TPH has one major problem: Columns for properties declared by subclasses will be nullable in the database. For example, Code First created an (INT, NULL) column to map CardType property in CreditCard class. However, in a typical mapping scenario, Code First always creates an (INT, NOT NULL) column in the database for an int property in persistent class. But in this case, since BankAccount instance won’t have a CardType property, the CardType field must be NULL for that row so Code First creates an (INT, NULL) instead. If your subclasses each define several non-nullable properties, the loss of NOT NULL constraints may be a serious problem from the point of view of data integrity.

TPH Violates the Third Normal Form

Another important issue is normalization. We’ve created functional dependencies between nonkey columns, violating the third normal form. Basically, the value of Discriminator column determines the corresponding values of the columns that belong to the subclasses (e.g. BankName) but Discriminator is not part of the primary key for the table. As always, denormalization for performance can be misleading, because it sacrifices long-term stability, maintainability, and the integrity of data for immediate gains that may be also achieved by proper optimization of the SQL execution plans (in other words, ask your DBA).

Generated SQL Query

Let's take a look at the SQL statements that EF Code First sends to the database when we write queries in LINQ to Entities or EntitySQL. For example, the polymorphic query for BillingDetails that you saw, generates the following SQL statement:
SELECT 
[Extent1].[Discriminator] AS [Discriminator], 
[Extent1].[BillingDetailId] AS [BillingDetailId], 
[Extent1].[Owner] AS [Owner], 
[Extent1].[Number] AS [Number], 
[Extent1].[BankName] AS [BankName], 
[Extent1].[Swift] AS [Swift], 
[Extent1].[CardType] AS [CardType], 
[Extent1].[ExpiryMonth] AS [ExpiryMonth], 
[Extent1].[ExpiryYear] AS [ExpiryYear]
FROM [dbo].[BillingDetails] AS [Extent1]
WHERE [Extent1].[Discriminator] IN ('BankAccount','CreditCard')
Or the non-polymorphic query for the BankAccount subclass generates this SQL statement:
SELECT 
[Extent1].[BillingDetailId] AS [BillingDetailId], 
[Extent1].[Owner] AS [Owner], 
[Extent1].[Number] AS [Number], 
[Extent1].[BankName] AS [BankName], 
[Extent1].[Swift] AS [Swift]
FROM [dbo].[BillingDetails] AS [Extent1]
WHERE [Extent1].[Discriminator] = 'BankAccount'
Note how Code First adds a restriction on the discriminator column and also how it only selects those columns that belong to BankAccount entity.

Change Discriminator Column Data Type and Values With Fluent API 

Sometimes, especially in legacy schemas, you need to override the conventions for the discriminator column so that Code First can work with the schema. The following fluent API code will change the discriminator column name to "BillingDetailType" and the values to "BA" and "CC" for BankAccount and CreditCard respectively:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<BillingDetail>()
                .Map<BankAccount>(m => m.Requires("BillingDetailType").HasValue("BA"))
                .Map<CreditCard>(m => m.Requires("BillingDetailType").HasValue("CC"));
}
Also, changing the data type of discriminator column is interesting. In the above code, we passed strings to HasValue method but this method has been defined to accepts a type of object:
public void HasValue(object value);
Therefore, if for example we pass a value of type int to it then Code First not only use our desired values (i.e. 1 & 2) in the discriminator column but also changes the column type to be (INT, NOT NULL):
modelBuilder.Entity<BillingDetail>()
            .Map<BankAccount>(m => m.Requires("BillingDetailType").HasValue(1))
            .Map<CreditCard>(m => m.Requires("BillingDetailType").HasValue(2));

Summary

In this post we learned about Table per Hierarchy as the default mapping strategy in Code First. The disadvantages of the TPH strategy may be too serious for your design—after all, denormalized schemas can become a major burden in the long run. Your DBA may not like it at all. In the next post, we will learn about Table per Type (TPT) strategy that doesn’t expose you to this problem.

References

Published Friday, December 24, 2010 4:47 AM by mortezam

Comments

# re: Inheritance Mapping Strategies with Entity Framework Code First CTP5 Part 1: Table per Hierarchy (TPH)

Friday, December 24, 2010 1:35 AM by webdiyer

nice feature, thanks

# re: Inheritance Mapping Strategies with Entity Framework Code First CTP5 Part 1: Table per Hierarchy (TPH)

Friday, December 24, 2010 5:03 AM by Ericpoon

Nice post, but some words on the right side maybe over the content div, so I cannot read it through.

# re: Inheritance Mapping Strategies with Entity Framework Code First CTP5 Part 1: Table per Hierarchy (TPH)

Friday, December 24, 2010 5:42 AM by David

Great post, thanks.  Using this method how can I access the discriminator value from my object if I want to use it in a projection? Like context.BillingDetails.Select(x => new { Number = x.Number, DiscrimitatorValue = /* how do I get the discriminator value? */ });

# re: Inheritance Mapping Strategies with Entity Framework Code First CTP5 Part 1: Table per Hierarchy (TPH)

Friday, December 24, 2010 4:44 PM by mortezam
@Ericpoon: I’ve done some modifications so now it should be fully viewable on all screens with a resolution higher than 1024x768. Please check it out and let me know if you still have difficulties in viewing the blog post. Thank you for letting me know about this, really appreciate it :)

# re: Inheritance Mapping Strategies with Entity Framework Code First CTP5 Part 1: Table per Hierarchy (TPH)

Friday, December 24, 2010 6:39 PM by mortezam
@David: If you want to read the discriminator value to filter the rows then you should instead write a non-polymorphic query like the one you saw in the post: context.BillingDetails.OfType<BankAccount>(). But if you are interested in the discriminator value itself — for example let’s say for an Ad-hoc report — then you should be aware that the discriminator column is used internally by Code First and you cannnot read/write its values from an inheritance mapping standpoint. To achieve this, the best way that I can think of is to use the new SqlQuery method on DbContext.Database which allows raw SQL queries to be executed against the database. But first we need to create a new non-persistent class since SqlQuery method is generic and needs a type to materialize the query results into (we cannot reuse BillingDetail class since Discriminator is not exposed in there). I named this new type as BillingReport:

[NotMapped]
public class BillingReport
{
   public int BillingId { get; set; }
   public string Number { get; set; }
   public string Owner { get; set; }
   public string Discriminator { get; set; }
   public string BankName { get; set; }
   public string Swift { get; set; }
   public int? CardType { get; set; }
   public string ExpiryMonth { get; set; }
   public string ExpiryYear { get; set; }
}
Now we can give this type to the SqlQuery method along with our custom SQL query:

List<BillingReport> reports = context.Database.SqlQuery<BillingReport>("SELECT * FROM BillingDetails").ToList();

Running this code will give us all the rows in the BillingDetails table with all the columns including the Discriminator. Hope this helps and thanks for your great question, I might add this trick to the post as well :)

# re: Inheritance Mapping Strategies with Entity Framework Code First CTP5 Part 1: Table per Hierarchy (TPH)

Sunday, December 26, 2010 1:22 AM by Venkat

Hello, which tool do you use for drawing UML diagrams ?

# re: Inheritance Mapping Strategies with Entity Framework Code First CTP5 Part 1: Table per Hierarchy (TPH)

Sunday, December 26, 2010 11:31 AM by mortezam
@Venkat: I use Visual Studio 2010 Architecture and Modeling features which come with the Ultimate edition. I’ve added a Modeling Project to my solution and created UML diagrams in there.

# re: Inheritance Mapping Strategies with Entity Framework Code First CTP5: Part 1 – Table per Hierarchy (TPH)

Tuesday, January 04, 2011 10:51 AM by BatsIhor

I think you should start write some small project using ASP MVC, and summarize your posts in it.

# re: Inheritance with EF Code First CTP5: Part 1 – Table per Hierarchy (TPH)

Thursday, January 06, 2011 5:46 PM by mortezam
@BatsIhor: That’s a very good idea. I will definitely create a sample project like the one you suggested once I finish the Associations in EF Code First series. Thanks :)

# re: Inheritance with EF Code First CTP5: Part 1 – Table per Hierarchy (TPH)

Tuesday, January 11, 2011 5:54 AM by Sébastien F.

First of all, thank you for those post, it's really a great help when trying things with EF CF !

Do you know if there is a way, via the Fluent Api, to ignore a field on a subclass ?

I tried that : Ignore(o => ((MyDerivedClass)o).MyFieldToIgnore) but I get a "System.InvalidOperationException: The expression 'o => Convert(o).MyFieldToIgnore' is not a valid property expression. It must be of the form 'e => e.Property'.

# re: Inheritance with EF Code First CTP5: Part 1 – Table per Hierarchy (TPH)

Tuesday, January 11, 2011 9:26 PM by mortezam
@Sébastien F.: Yes, for that you need to call Ignore method and provide it with the specific property on the subclass that you want to ignore. For example, here is the fluent API code to ignore CardType in CreditCard subclass:

modelBuilder.Entity<CreditCard>().Ignore(c => c.CardType);

Alternatively, you may want to use Data Annotations for this matter. Placing a NotMapped attribute on the property will have the same result as the previous code:

public class CreditCard : BillingDetail
{
   [NotMapped]
   public int CardType { get; set; }
   public string ExpiryMonth { get; set; }
   public string ExpiryYear { get; set; }                
}

Also thanks for your comment, I am glad you found it useful :)

# re: Inheritance with EF Code First CTP5: Part 1 – Table per Hierarchy (TPH)

Wednesday, January 12, 2011 8:32 AM by Cosmin Onea

Can one of the subclasses have a required relationship?

E.g. Imagine CreditCard.CardType was a foreign key to CreditCardTypes table.

How would you map that?

In my case if I use HasRequired like

modelBuilder.Entity<CreditCard>().HasRequired(ct => ct.CardType);

I get

"Two entities with different keys are mapped to the same row. Ensure these two mapping fragments do not map two groups of entities with different keys to two overlapping groups of rows.

Problem in mapping fragments starting at lines 6, 49:Entity

Types CodeFirstNamespace.BankAccount, CodeFirstNamespace.CreditCard are being mapped to the same rows in table BillingDetails. Mapping conditions can be used to distinguish the rows that these types are mapped to."

# re: Inheritance with EF Code First CTP5: Part 1 – Table per Hierarchy (TPH)

Thursday, January 13, 2011 10:18 AM by mortezam
@Cosmin Onea: Yes, this scenario is perfectly possible with Code First. To create this association, first we add a new CreditCardType class to our data model:

public class CreditCardType
{
    public int CreditCardTypeId { get; set; }
    public string CardDescription { get; set; }
}

Then, we create a many-to-one association from CreditCard to CreditCardType by adding a new navigation property to our CreditCard subclass:

public class CreditCard : BillingDetail
{
    public int CardTypeId { get; set; }
    public string ExpiryMonth { get; set; }
    public string ExpiryYear { get; set; }
    public CreditCardType CreditCardType { get; set; }
}

(As you can see, I renamed CardType to CardTypeId so that it will be better distinguished from the new CreditCardType navigation property).

The last step would be to let Code First know about the foreign key for this association which is going to be our CardTypeId property:

public class InheritanceMappingContext : DbContext
{
    public DbSet<BillingDetail> BillingDetails { get; set; }
    public DbSet<CreditCardType> CreditCardTypes { get; set; }
       
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<CreditCard>().HasRequired(c => c.CreditCardType).WithMany().HasForeignKey(c => c.CardTypeId);
    }
}

Running this code will turn CardTypeId column to a foreign key referencing CreditCardTypes table. The interesting point is that even though we use HasRequired() method to configure this association (and also the fact that CardTypeId is not nullable) but still CardTypeId will be mappaed to a (INT, NULL) column since we are in a TPH scenario which means it still needs to be null for BankAccount records in BillingDetails table. Hope this helps :)

# re: Inheritance with EF Code First CTP5: Part 1 – Table per Hierarchy (TPH)

Sunday, February 06, 2011 11:03 PM by TearlessLight

Awesome!  Finally, after a week of searching, this is the first non-sensical explanation of what and how that stupid discriminator column does.  I mean, I know what it is for but noe one had any explnantion of how it operates.  Every example you see out there (besides this one) talks about how you can shoose your own and set conditions on the mappings but none (NONE) of them work and are not supported but this explanation makes sense.  You don't need to have those manual conditions set.

# re: Inheritance with EF Code First CTP5: Part 1 – Table per Hierarchy (TPH)

Monday, February 21, 2011 6:47 AM by Nekketsu

Very nice posts!!!

Is it posible to especify the type of discriminator column (Varchar(10), Varchar(25), etc)?

Thank you!

# re: Inheritance with EF Code First CTP5: Part 1 – Table per Hierarchy (TPH)

Monday, February 21, 2011 8:11 PM by mortezam
@Nekketsu: Thanks for your comment. Currently there is no way to explicitly specify the data type of the discriminator column in Code First. It is assumed from the type of the constant assigned to it in the fluent API code (like the example you saw in this post that the type inferred to be an int.). In fact, this is something that the EF team are looking into to see if they can enable it for the RTM.

For now the only way that I can think of is to change the discriminator column type directly by using the new SqlCommand method which allows raw SQL commands to be executed against the database. The best place to invoke SqlCommand method for this matter is inside a Seed method that has been overridden in a custom Initializer class:

protected override void Seed(EntityMappingContext context)
{
   context.Database.SqlCommand("ALTER TABLE BillingDetails ALTER COLUMN Discriminator NVARCHAR(20)");
}

Hope this helps :)

# re: Inheritance with EF Code First CTP5: Part 1 – Table per Hierarchy (TPH)

Tuesday, February 22, 2011 1:47 PM by TerminalFrost

Just wanted to say thanks! This answered a lot of questions I had not only about EF but OO inheritance in relational databases as well.

# re: Inheritance with EF Code First CTP5: Part 1 – Table per Hierarchy (TPH)

Wednesday, March 16, 2011 12:31 PM by Jan C. de Graaf

First, thanks for the article.

I have an issue with a TPH implementation using another model. Translated to your sample/structure the following code gives me an exception:

var creditCard = context.CreditCards.First();

var creditCardNowInDb = context.Entry(creditCard).GetDatabaseValues().ToObject();

The exception thrown is:

'CardType' is not a member of type 'CodeFirstNamespace.BillingDetail' in the currently loaded schemas. Near escaped identifier, line xx, column xx.

Any ideas?

Thanks, Jan C. de Graaf

# re: Inheritance with EF Code First CTP5: Part 1 – Table per Hierarchy (TPH)

Thursday, March 17, 2011 3:02 PM by mortezam
@Jan C. de Graaf: This seems to be a bug that existed in CTP5 which has not been fixed in EF 4.1 RC yet. I saw your question on MSDN forum so we have to wait for EF team to confirm this bug. Meanwhile, as a workaround, you can use the Reload method (context.Entry(creditCard).Reload()) and then clone the creditCard object yourself, if that was the intention behind using GetDatabaseValues method. Thanks :)

# Inheritance with Entity Framework 4.1 &laquo; Nathan&#039;s blog

Friday, April 08, 2011 9:41 AM by Inheritance with Entity Framework 4.1 « Nathan's blog

Pingback from  Inheritance with Entity Framework 4.1 &laquo; Nathan&#039;s blog

# Inheritance with Entity Framework 4.1 &laquo; Nathan&#039;s blog

Friday, April 08, 2011 10:12 AM by Inheritance with Entity Framework 4.1 « Nathan's blog

Pingback from  Inheritance with Entity Framework 4.1 &laquo; Nathan&#039;s blog

# Inheritance with Entity Framework 4.1 &laquo; Nathan&#039;s blog

Friday, April 08, 2011 11:21 AM by Inheritance with Entity Framework 4.1 « Nathan's blog

Pingback from  Inheritance with Entity Framework 4.1 &laquo; Nathan&#039;s blog

# Entity Framework 4.1 Code First????????????????????? &#8211; jiaxingseng &laquo; Hot Trends

Pingback from  Entity Framework 4.1 Code First????????????????????? &#8211; jiaxingseng  &laquo;  Hot Trends

# re: Inheritance with EF Code First CTP5: Part 1 – Table per Hierarchy (TPH)

Tuesday, May 10, 2011 3:22 AM by Aamir Ali

For accessing Discriminator column i added one Discriminator(notmapped) column to BillingDetail class but when i try to access, it always gives me null value why is it so??

Do i always have to make a new notmapped class to access the discriminator column is there no other way to do it???

# re: Inheritance with EF Code First CTP5: Part 1 – Table per Hierarchy (TPH)

Wednesday, May 11, 2011 10:56 AM by mortezam
@Aamir Ali: Please read my answer to David’s comment above. And yes, you always have to create a separate class to read the discriminator column value since like I said the discriminator column is internally used by EF and you cannot access it from the classes that participate in the inheritance hierarchy.

# re: Inheritance with EF Code First CTP5: Part 1 – Table per Hierarchy (TPH)

Wednesday, May 11, 2011 1:48 PM by bteal

Thanks for the post. I'm using TPH on a small project that has a legacy schema and I'm running into a problem using a custom discriminator column. I'm using the fluent API to map the subclassess to the descriminator and everything works fine when reading data. On an add operation EF is throwing an exception saying that my discriminator column cannot be null. Is this something that EF should handle automatically under the covers based on the subclass type I'm trying to add or do I have to do something explicitly?

# re: Inheritance with EF Code First CTP5: Part 1 – Table per Hierarchy (TPH)

Thursday, May 12, 2011 10:20 AM by mortezam
@bteal: Yes, EF internally writes the discriminator column value based on the object type and you don’t need to do anything special in this regard. Could you please post your object model as well as the code that throws when you try to add an object to the hierarchy?

# re: Inheritance with EF Code First CTP5: Part 1 – Table per Hierarchy (TPH)

Wednesday, May 18, 2011 11:37 AM by Anderson Fortaleza

Mr. Manavi, thank you for this most excellent and useful article!

# re: Inheritance with EF Code First CTP5: Part 1 – Table per Hierarchy (TPH)

Friday, May 27, 2011 4:10 PM by horsinaround

Thank you for your article!  There is so little about this topic out there at this time.  

With a discriminator column as part of a complex primary key in a legacy table, is it even possible to use TPH in Code First?  I am reading this: "Basically, the value of Discriminator column determines the corresponding values of the columns that belong to the subclasses (e.g. BankName) but Discriminator is not part of the primary key for the table." to mean No to my question.  I am having a difficult time getting to work. Thanks in advance for a reply.

# re: Inheritance with EF Code First CTP5: Part 1 – Table per Hierarchy (TPH)

Saturday, May 28, 2011 3:05 PM by mortezam
@horsinaround: Actually by that line I was more explaining why a TPH mapping violates the third normal form but the answer to your question is still a no, unfortunately. The reason for that is because the discriminator column is internally used by EF and cannot be exposed as a property in the subclasses so you can’t register it as a composite PK along with the other PK coming from the base class. If you don’t expose it and configure it as the discriminator column for the TPH mapping then it wouldn’t be part of the PK, so either ways we are out of luck to map this legacy table to an inheritance hierarchy.

# Entity Framework 4.1 Code First learning path (2)

Friday, June 24, 2011 7:49 PM by Entity Framework 4.1 Code First learning path (2)

Pingback from  Entity Framework 4.1 Code First learning path (2)

# re: Inheritance with EF Code First CTP5: Part 1 – Table per Hierarchy (TPH)

Monday, July 11, 2011 9:13 PM by Venkatesh (heman_1978@hotmail.com)

Hi,

I have created the same example using a custom discriminator column and is resulting in an issue. I have created a question in MSDN forum. The link to the same is social.msdn.microsoft.com/.../d09fb12a-4751-4292-853a-a99759984cd6

could you please look into the query and let me know what mistake I made.

Thanks and regards

Venkatesh. S

# re: Inheritance with EF Code First CTP5: Part 1 – Table per Hierarchy (TPH)

Tuesday, August 02, 2011 12:22 PM by drammer

Hi,

I am having trouble mapping an entity that derives from a class like CreditCard. I am doing something like the following:

BillingDetail (abstract / own table)

- BillingDetailType (discriminator) (e.g. BA, CC)

CreditCard (abstract / own table) inherits from BillingDetail

- CardType (discriminator) (e.g. Visa, MasterCard)

VisaCard (concrete / CreditCard table) inherits from CreditCard

- Level int

MasterCard (concrete / CreditCard table) inherits from CreditCard

- Level int

- Group int

I can't formulate the correct mapping.

# re: Inheritance with EF Code First CTP5: Part 1 – Table per Hierarchy (TPH)

Sunday, August 07, 2011 3:20 PM by mortezam
@drammer: What I understand from your desired schema is that in your first level of hierarchy, you want to use TPT to map the CreditCard class and also TPH to map other BillingDetail’s subtypes such as BankAccount. This is NOT possible. You cannot mix inheritance hierarchies at a particular level. If you choose to have a separate table for the CreditCard entity then all other subclasses at the same level (e.g. BankAccount) also need to be mapped to a separate table as well. Mixing inheritance hierarchies on different levels is possible though. In your case, you can use TPT to map the first level of your hierarchy (i.e. CreditCard and BankAccount) and TPH to map the second level (i.e. VisaCard and MasterCard). The following object model shows how this can be done:

public abstract class BillingDetail
{
    public int BillingDetailId { get; set; }
    public string Number { get; set; }
}

public class BankAccount : BillingDetail
{
    public string BankName { get; set; }
}

public abstract class CreditCard : BillingDetail
{
    public int Level { get; set; }
}

public class VisaCard : CreditCard
{
    [Required]
    public string CardName { get; set; }
}

public class MasterCard : CreditCard
{
    public int Group { get; set; }
}
   
public class Context : DbContext
{
    public DbSet<BillingDetail> BillingDetails { get; set; }       
    public DbSet<CreditCard> CreditCards { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<BillingDetail>().ToTable("BillingDetail");           
        modelBuilder.Entity<BankAccount>().ToTable("BankAccount");
                       
        modelBuilder.Entity<CreditCard>()
                    .Map<VisaCard>(m => m.Requires(vc => vc.CardName).HasValue())
                    .Map<MasterCard>(m => m.Requires(mc => mc.Group).HasValue())
                    .ToTable("CreditCard");
    }
}

This mapping gives you almost your desired schema except that I couldn’t find a way to use a discriminator column like CardType on CreditCard table. Instead, I designate one column on each of the subclasses to be not-null for a row that represents an instance of that subclass. So for example a VisaCard row on the CreditCard table will always have a value for CardName and NULL for Group. Hope this helps.

# EF 4.1 Mapping Inheritence on a Many-to-Many relationship - Programmers Goodies

Pingback from  EF 4.1 Mapping Inheritence on a Many-to-Many relationship - Programmers Goodies

# How to map class hierarchy (base class and inherited classes) to a database - Programmers Goodies

Pingback from  How to map class hierarchy (base class and inherited classes) to a database - Programmers Goodies

# re: Inheritance with EF Code First CTP5: Part 1 – Table per Hierarchy (TPH)

Wednesday, September 21, 2011 9:57 AM by Mark Phillips

Thank you.  very helpful

# re: Inheritance with EF Code First CTP5: Part 1 – Table per Hierarchy (TPH)

Monday, October 03, 2011 4:39 PM by Tim

Hi, the current version of EF (SP2) does not support passing in a value in the "HasValue" method.  Let's say I have a table "ContactPoints", and there's a "ContactPointTypeID" column which will be used as the discriminator.  How would I map that into different subclasses of EmailAddress, PhoneNumber, and PostalAddress?

Ex. (does not work):

builder

   .Entity<ContactPoint>()

   .HasKey(p => p.ID)

   .Map<EmailAddress>(m =>

   {

       m.MapInheritedProperties();

       m.Requires(cp => cp.PointTypeID).HasValue(/* There is no way to pass in a value! There's no parameters! */);

   })

   .ToTable("ContactPoint", "contact");

# re: Inheritance with EF Code First CTP5: Part 1 – Table per Hierarchy (TPH)

Thursday, October 06, 2011 10:08 PM by mortezam
@Tim: The following object model will create a TPH mapping for your domain:

public abstract class ContactPoint
{
    public int Id { get; set; }
}

public class EmailAddress : ContactPoint
{
    public string Email { get; set; }
}

public class PhoneNumber : ContactPoint
{
    public string Phone { get; set; }
}

public class PostalAddress : ContactPoint
{
    public string Postal { get; set; }

       
public class Context : DbContext
{
    public DbSet<ContactPoint> ContactPoints { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<ContactPoint>()
                    .Map<EmailAddress>(m => m.Requires("ContactPointTypeID").HasValue("EA"))
                    .Map<PhoneNumber>(m => m.Requires("ContactPointTypeID").HasValue("PN"))
                    .Map<PostalAddress>(m => m.Requires("ContactPointTypeID").HasValue("PA"))
                    .ToTable("ContactPoint", "Contact");
    }
}

Please note that the Requires method overload that you’ve used is NOT meant to be used when you have a discriminator column. It’s only for when you want to designate the subtype based on the nullability of one column in the mapped table. See my answer to “drammer” above for an example. Hope this helps.

# Entity framework code first creates ???discriminator??? column - Programmers Goodies

Pingback from  Entity framework code first creates ???discriminator??? column - Programmers Goodies

# Entity Framework Code First 0 to 1 mapping - Programmers Goodies

Pingback from  Entity Framework Code First 0 to 1 mapping - Programmers Goodies

# re: Inheritance with EF Code First CTP5: Part 1 – Table per Hierarchy (TPH)

Wednesday, October 26, 2011 2:27 PM by Jonny

Hi!

Great post (as all of your others regarding EF 4.1 Code First).

I've got one problem, I have implemented the "State pattern" and the state object uses "table per hierarchy". I have an Order entity that contains a State entity, and the State entity contains the corrensponding Order entity.

When I create my Order it gets the state Created and when I save it, it has the right state. When I read my Order back (throuh a repository) and manipulate it to change its state and save it again and then read it back once again it still has the same state (Created).

If I dont save the created Order until it has a new state, that state will be saved correctly. So the problem is that once the Order is saved I cant change the state.

Sorry for my poor english but I hope you understand my problem!?

# re: Inheritance with EF Code First CTP5: Part 1 – Table per Hierarchy (TPH)

Thursday, October 27, 2011 1:58 PM by Jonny

Nevermind my question, I found the problem.

# re: Inheritance with EF Code First CTP5: Part 1 – Table per Hierarchy (TPH)

Sunday, November 06, 2011 5:17 PM by rekna

Consider following TPH scenario :

A (base class)

AB (inherited class) FK referenceId  => reference to B.Id

AC (inherited class) FK referenecId  => reference to B.Id

AD (inherited class) no reference to B

I can't get this configured. It looks like it is thinking there should be 2 FK's referenceId and referenceId2, but I want it to map to the same referenceId (there should be only one column referenceId in the table mapped to A)

P.S. I already have a table (I'm not generating it from code).

# re: Inheritance with EF Code First: Part 1 – Table per Hierarchy (TPH)

Friday, November 18, 2011 11:50 AM by mortezam
@rekna: This is not possible. Best thing you can do is to move the B reference to the base class (class A), like the following object model:

class A
{
    public int Id { get; set; }
    public int BId { get; set; }
    public B B { get; set; }
}

class B
{
    public int BId { get; set; }
}

class AB : A { }

class AC : A { }

class AD : A { }

# Inheritance with EF Code First: Part 1 ??? Table per Hierarchy (TPH) | My Blog

Pingback from  Inheritance with EF Code First: Part 1 ??? Table per Hierarchy (TPH)  | My Blog

# re: Inheritance with EF Code First: Part 1 – Table per Hierarchy (TPH)

Friday, February 10, 2012 8:52 PM by mattjcowan

This mapping no longer works it seems in ef 4.3 beta (social.msdn.microsoft.com/.../de137559-a7c7-404f-a6b1-96be4b12bab0)

# re: Inheritance with EF Code First: Part 1 – Table per Hierarchy (TPH)

Friday, April 06, 2012 5:00 AM by Hitesh

Is it possible to use Interface as Navigational and Enum Property?

Can I use IContentSource which is mapped to ContentSource in below example?

public enum ContentType

{

Static,

Dynamic

}

public interface Content

{

IContentSource ContentSource { get; set; }

ContentType Type { get; }

}

public interface IContentSource :

{

Guid Id { get; set; }

}

public abstract class ContentSource

{

public Guid Id { get; set; }

}

# re: Inheritance with EF Code First: Part 1 – Table per Hierarchy (TPH)

Friday, August 03, 2012 6:02 AM by Pak

Hello! Would you mind if I share your blog with my twitter group Theres lots of folks

that I think would really appreciate your content. Please let me know.

Thank you

# re: Inheritance with EF Code First: Part 1 – Table per Hierarchy (TPH)

Thursday, August 09, 2012 9:35 AM by Simon Harris

Great post - Cleared up a few grey areas for me. Thank you.

# re: Inheritance with EF Code First: Part 1 – Table per Hierarchy (TPH)

Tuesday, September 18, 2012 6:54 AM by Ph

Good day!

I implement this article in my model and i get exception on update-database: The new name 'Discriminator' is already in use as a COLUMN name and would cause a duplicate that is not permitted. I use EF 5 and Visual studio 2012.

If i implement discriminator myself like this:

           modelBuilder.Entity<Discount>()

               .Map(m =>

                   {

                       m.MapInheritedProperties();

                       m.ToTable("fattoDiscounts");

                   })

               .Map<ConstantDiscount>(m => m.Requires("DiscountType").HasValue("ConstantDiscount"))

               .Map<CountDiscount>(m => m.Requires("DiscountType").HasValue("CountDiscount"))

               .Map<CapacityDiscount>(m => m.Requires("DiscountType").HasValue("CapacityDiscount"))

               .Map<DateDiscount>(m => m.Requires("DiscountType").HasValue("DateDiscount"));

I have a following exception on update-database step: The new name 'DiscountType' is already in use as a COLUMN name and would cause a duplicate that is not permitted.

PS: all discounts in this example are children of Discount abstract class.

# re: Inheritance with EF Code First: Part 1 – Table per Hierarchy (TPH)

Monday, December 17, 2012 3:31 PM by Efy

Thanks, your explanations are excellent!

# re: Inheritance with EF Code First: Part 1 – Table per Hierarchy (TPH)

Monday, January 14, 2013 6:20 PM by Conklin

This is really interesting, You are a very skilled blogger.

I have joined your feed and look forward to seeking

more of your wonderful post. Also, I've shared your site in my social networks!

# re: Inheritance with EF Code First: Part 1 – Table per Hierarchy (TPH)

Sunday, March 17, 2013 7:14 AM by nolvoffw@gmail.com

jouer à des jeux et regarder leurs meilleures vidéos de leurs 3Ds , Si vous voulez flasher votre carte?r4i gold Pro. Oui…mais ?a n’a pas l’air très bon pour les anciens utilisateurs de la r4i-sdhc 3DS ! Entra?nement Cérébral du diabolique est de former votre matière grise en complétant une série d&rsquo? il est possible de mémoriser plus de jeux , étant donné que les systèmes Nintendo vendus au Chili sont les mêmes que ceux qui sont vendus en Amérique du Nord.  <a href="http://www.r4-i.info/" title="carte r4i">carte r4i</a>

# re: Inheritance with EF Code First: Part 1 – Table per Hierarchy (TPH)

Monday, March 18, 2013 12:27 AM by ckreaokfjo@gmail.com

Additionally , they say it could mean something in addition to the goddess herself. So it is anybody's suppose.

# re: Inheritance with EF Code First: Part 1 – Table per Hierarchy (TPH)

Tuesday, March 19, 2013 6:10 AM by chippers

Im stuck with how you would show the different models given a list like above ie

IQueryable<BillingDetail> linqQuery = from b in context.BillingDetails select b;

List<BillingDetail> billingDetails = linqQuery.ToList();

In a view. for example if you wanted a list of all billing details and you then wanted show all the details on a view how is that done?

Many Thanks

# re: Inheritance with EF Code First: Part 1 – Table per Hierarchy (TPH)

Saturday, March 23, 2013 1:36 PM by Bryson

I like the helpful information you provide in your articles.

I’ll bookmark your blog and check again here frequently.

I am quite sure I’ll learn many new stuff right

here! Good luck for the next!

# re: Inheritance with EF Code First: Part 1 – Table per Hierarchy (TPH)

Saturday, March 30, 2013 3:49 PM by eijykndfsmv@gmail.com

So significantly I shed 10lbs in three weeks, I stopped taking the products simply because I had been going through something but have kept the weight off. I'll start out back again once again simply because I hope to loose 20lbs extra.

# re: Inheritance with EF Code First: Part 1 – Table per Hierarchy (TPH)

Sunday, March 31, 2013 12:12 PM by jqcusw@gmail.com

I appreciate this item, and it actually does function to melt the fat! I was gaining weight rapid until I started getting my Fruta Planta , and without having dieting, I just quit putting on the weight. And, the top thing is that when i do watch what I consume, I slim down a lot faster than normal.

# re: Inheritance with EF Code First: Part 1 – Table per Hierarchy (TPH)

Monday, April 08, 2013 12:57 PM by Jason

This is an excellent article.  I can actually understand it.  Well written, thanks!!

# re: Inheritance with EF Code First: Part 1 – Table per Hierarchy (TPH)

Monday, April 08, 2013 5:24 PM by Putnam

Wonderful work! This is the type of information that should be shared around the net.

Shame on Google for not positioning this post higher!

# re: Inheritance with EF Code First: Part 1 – Table per Hierarchy (TPH)

Tuesday, April 09, 2013 4:22 PM by Temple

For most recent news you have to pay a visit internet and on world-wide-web I found this site as a most

excellent web page for latest updates.

# re: Inheritance with EF Code First: Part 1 – Table per Hierarchy (TPH)

Thursday, April 11, 2013 6:17 PM by Caldwell

Every weekend i used to visit this web page, as i wish for enjoyment,

for the reason that this this site conations in fact nice funny data too.

# re: Inheritance with EF Code First: Part 1 – Table per Hierarchy (TPH)

Thursday, April 11, 2013 9:06 PM by Benge

Please let me know if you're looking for a writer for your weblog. You have some really great posts and I think I would be a good asset. If you ever want to take some of the load off, I'd absolutely love to write some content for your blog in exchange for a

link back to mine. Please send me an email if interested. Cheers!

# re: Inheritance with EF Code First: Part 1 – Table per Hierarchy (TPH)

Friday, April 12, 2013 6:15 PM by Cheek

What i don't realize is in reality how you're not actually much more neatly-favored than you might be right now.

You're so intelligent. You recognize therefore considerably when it comes to this subject, made me individually believe it from so many varied angles. Its like women and men aren't

interested until it's something to do with Lady gaga! Your individual stuffs great. At all times deal with it up!

# re: Inheritance with EF Code First: Part 1 – Table per Hierarchy (TPH)

Friday, April 12, 2013 7:14 PM by Benavidez

Oh my goodness! Impressive article dude! Thanks, However I am encountering difficulties with your RSS.

I don't understand why I can't subscribe to it. Is there anybody else getting the same RSS problems?

Anyone who knows the answer can you kindly respond?

Thanx!!

# re: Inheritance with EF Code First: Part 1 – Table per Hierarchy (TPH)

Saturday, April 13, 2013 12:24 AM by Bowens

I don't even know how I ended up here, but I thought this post was great. I do not know who you are but definitely you are going to a famous blogger if you aren't already ;

) Cheers!

# re: Inheritance with EF Code First: Part 1 – Table per Hierarchy (TPH)

Saturday, April 13, 2013 5:29 PM by Hoskins

I think everything posted made a ton of sense.

However, consider this, suppose you composed a

catchier post title? I mean, I don't want to tell you how to run your website, however what if you added something that grabbed folk's attention?

I mean Inheritance with EF Code First: Part 1 – Table per Hierarchy (TPH) - Enterprise .

Net is kinda plain. You might look at Yahoo's home page and watch how they write news titles to get viewers to open the links. You might add a related video or a related picture or two to get readers interested about what you've written.

Just my opinion, it might bring your blog a little livelier.

# re: Inheritance with EF Code First: Part 1 – Table per Hierarchy (TPH)

Saturday, April 13, 2013 11:03 PM by Cohen

That is really interesting, You're a very professional blogger. I have joined your feed and look ahead to in the hunt for more of your fantastic post. Additionally, I have shared your web site in my social networks

# re: Inheritance with EF Code First: Part 1 – Table per Hierarchy (TPH)

Sunday, April 14, 2013 9:25 AM by Strange

I could not resist commenting. Perfectly written!

# re: Inheritance with EF Code First: Part 1 – Table per Hierarchy (TPH)

Sunday, April 14, 2013 1:52 PM by Oconnell

Pretty! This has been a really wonderful post.

Thanks for providing this information.

# re: Inheritance with EF Code First: Part 1 – Table per Hierarchy (TPH)

Monday, April 15, 2013 12:33 AM by Nunes

Hi there, all is going fine here and ofcourse every one is sharing information, that's truly fine, keep up writing.

# re: Inheritance with EF Code First: Part 1 – Table per Hierarchy (TPH)

Monday, April 15, 2013 9:38 PM by Mcpherson

What i do not realize is if truth be told how you are no longer really much more well-appreciated

than you might be right now. You're very intelligent. You already know thus considerably in terms of this subject, produced me individually consider it from numerous numerous angles. Its like men and women aren't

interested until it is one thing to do with Girl gaga!

Your individual stuffs outstanding. All the time care for it up!

# re: Inheritance with EF Code First: Part 1 – Table per Hierarchy (TPH)

Wednesday, April 17, 2013 11:34 PM by Whited

Definitely imagine that that you said. Your favourite reason

appeared to be on the net the simplest factor to keep in

mind of. I say to you, I certainly get annoyed even as other people think about concerns that they plainly do not recognise about.

You controlled to hit the nail upon the highest as neatly as

outlined out the entire thing without having side effect ,

other folks could take a signal. Will likely be

again to get more. Thanks

# re: Inheritance with EF Code First: Part 1 – Table per Hierarchy (TPH)

Thursday, April 18, 2013 2:48 AM by Dalton

Way cool! Some extremely valid points! I appreciate you writing

this post plus the rest of the site is very

good.

# re: Inheritance with EF Code First: Part 1 – Table per Hierarchy (TPH)

Sunday, April 21, 2013 5:01 AM by Demarco

Hello there! This article couldn't be written much better! Reading through this post reminds me of my previous roommate! He continually kept preaching about this. I'll forward this post to him.

Pretty sure he will have a very good read. I appreciate

you for sharing!

# re: Inheritance with EF Code First: Part 1 – Table per Hierarchy (TPH)

Sunday, April 21, 2013 11:56 PM by Nunes

It's fantastic that you are getting ideas from this article as well as from our argument made here.

# re: Inheritance with EF Code First: Part 1 – Table per Hierarchy (TPH)

Thursday, May 02, 2013 6:39 PM by Fish

With havin so much content do you ever run into any issues of plagorism or copyright violation?

My blog has a lot of exclusive content I've either authored myself or outsourced but it looks like a lot of it is popping it up all over the web without my permission. Do you know any techniques to help reduce content from being stolen? I'd certainly appreciate it.

# re: Inheritance with EF Code First: Part 1 – Table per Hierarchy (TPH)

Thursday, May 02, 2013 8:23 PM by Paradis

Hi to all, for the reason that I am truly keen of reading this website's post to be updated regularly. It contains pleasant material.

# re: Inheritance with EF Code First: Part 1 – Table per Hierarchy (TPH)

Thursday, May 02, 2013 10:32 PM by Orton

Nice post. I learn something totally new and challenging on blogs I

stumbleupon on a daily basis. It's always useful to read through articles from other authors and use a little something from their sites.

# re: Inheritance with EF Code First: Part 1 – Table per Hierarchy (TPH)

Friday, May 03, 2013 12:24 AM by Goodman

I don't write many responses, however i did some searching and wound up here Inheritance with EF Code First: Part 1 – Table per Hierarchy (TPH) - Enterprise .Net. And I do have a couple of questions for you if you usually do not mind. Is it simply me or does it give the impression like some of the comments appear as if they are coming from brain dead individuals? :-P And, if you are posting on additional online sites, I'd like to keep up

with everything new you have to post. Could you list of the complete urls of your shared

pages like your linkedin profile, Facebook page or twitter feed?

# re: Inheritance with EF Code First: Part 1 – Table per Hierarchy (TPH)

Friday, May 03, 2013 2:14 AM by Saucedo

What's up, all is going perfectly here and ofcourse every one is sharing information, that's truly good,

keep up writing.

# re: Inheritance with EF Code First: Part 1 – Table per Hierarchy (TPH)

Saturday, May 04, 2013 8:28 PM by Aponte

Hi there, I enjoy reading through your post. I wanted to write a

little comment to support you.

# re: Inheritance with EF Code First: Part 1 – Table per Hierarchy (TPH)

Tuesday, May 07, 2013 8:58 PM by Aldrich

I do not even know how I finished up right here, however I believed this put up used

to be great. I don't recognize who you might be however definitely you're going to a famous

blogger if you happen to are not already. Cheers!

Leave a Comment

(required) 
(required) 
(optional)
(required)