Inheritance in the Entity Framework
One of the coolest features of the ADO.NET Entity Framework is the ability to use inheritance in your database! Very cool, but what does it mean, and why is it important?
War of the worlds
Relational
The world of relational data is based around tuples, which have an inherent two dimensional structure. Think of a database table with rows and columns; it is a very two dimensional idea. Relationships, UDTs, views, etc are all extensions of this two dimensional view. This structure allows for the power we know and love in products like SQL Server, with features like query optimization, indexes, views, etc.
Objects
Object oriented programming (OOP) drives higher developer productivity and allows for applications to better represent the world in which they operate. One of the ways that they do this is by utilizing inheritance. Inheritance allows for an application to better model the data, and also provides the ability to extend an existing model and application in interesting ways.
Union of worlds
While the relational model has a lot of power, its way of looking at the world is somewhat at odds with the gestalt of object oriented programming.
The Entity Framework helps bridge these worlds by bringing the power of inheritance to the world of data access in ways that make sense and allow for the best features of both to shine through. To illustrate this, we will look at some of the benefits of OOP, and see how the Entity Framework helps bring these benefits to the store.
Why OOP?
Problem Modeling
In OOP, inheritance is often used to represent objects that have a IS-A relationship. This simply means that one object is a specialization of the other. For example, think of an online store with Products. A Product has certain attributes and data associated with it. Now, there is also a Discontinued Product which has all the same data as a regular Product, but also something more, namely a discontinued date. You could create a new object to represent the Discontinued Product, but it makes a lot more sense to create a new object that inherits from Product, and adds the additional field. After all, programmers are lazy, and why would I want to write more code then I need to!
Application Extension
You’ve done such a great job, and this online store has such a great database and application driving it, it’s ready to expand into new markets. The store is ready to branch out into seasonal products!
This scenario really shows off the extension power of OOP. You simply need to write a new object that inherits from Product and applies some different logic in its methods. For example, you might only show summer products in the summer or automatically provide a 10% discount for summer products in the fall. And all of the existing systems to manage inventory, shopping carts, etc just continue to work, as everything is still made up of Products!
How the Entity Framework bridges the gap
The ideas presented above are fairly basic; generally introduced in OOP 101. So what is the big deal? Let’s look at how we apply these scenarios in the Entity Framework, so we can see how powerful it is. This will also give us an opportunity to dive into the specifics of how the translation of OOP ideas to the relational world works.
To make the scenario specific, let’s use the example of an online hardware store, with both Discontinued Products, and Seasonal Products. The Entity Data Model (CSDL) for the Products might look something like the following.
<EntityType Name="Product" Key="ProductID">
<Property Name="ProductID" Type="Int32" Nullable="false" />
<Property Name="Name" Type="String" MaxLength="500" Nullable="false"/>
<Property Name="Price" Type="Decimal" Nullable="false" />
</EntityType>
<EntityType Name="DiscontinuedProduct" BaseType="Product">
<Property Name="DiscontinuedDate" Type="DateTime" Nullable="false"/>
</EntityType>
<EntityType Name="SeasonalProduct" BaseType="Product">
<Property Name="OffSeasonDiscount" Type="Float" Nullable="false"/>
</EntityType>
The CLR code for this situation is not shown, but we would have the same inheritance hierarchy in the generated CLR classes, with the full capabilities that this implies. The interesting thing with respect to this post is the OO to relational mapping.
Table per Hierarchy
Let’s start with the Discontinued Product, and see how you might model this in a database. You know that you will need to maintain a list of discontinued products (to maintain referential integrity), so you might create a table that contains all products with data like the following.
ProductID |
Name |
Price |
Discontinued |
Discontinued Date |
1 |
Nail |
$1.40 |
No |
Null |
2 |
Bubble level |
$5.50 |
Yes |
2/2/07 |
How do you use inheritance with data like this? Looking at the data, you know that when the Discontinued field is true, we’re dealing with a discontinued product. This is exactly the way that Table per Hierarchy (TPH) works! The idea is that the entire OO hierarchy is contained in one table, with some column(s) acting as discriminator. The value of the discriminator is what informs the Entity Framework what OO type each row contains.
Comments
Anonymous
March 15, 2007
One thing I can see when looking at the blog source is that there is a fair amount of bloat due to teh MSOffice formatting. I wonder if, under some circumstances, this may cause slow rendering performance? I mention this because, on many sites, IE7 tends to build it's page very slowly. Not this on for me but it does happen. The same site on IE6 render norrmally. Is it machine settings or IE7 issues with some layouts?Anonymous
March 16, 2007
I was/am so busy in two projects , there was no time for any blah blah and blogging.. I still don't haveAnonymous
March 16, 2007
how do you manage polimorphic query with inheritance? In NHibernate if I use a TPC strategy, and I create a query "from BaseClass" I usually obtain a SELECT with UNION from all several table per concrete. Normally for a polimorphic query a TPH or a Table per Subclass strategy (S.Ambler definition) is better. Do Entity Framework manages polimorphic query? Thanks!Anonymous
March 17, 2007
First things first, how about adding 1:1 support :) Isn't that missing from this CTP? By the way, I'd like to have the EF use an NHibernate approach where mapping files are used as above, without cluttering the entity/value objects.Anonymous
March 17, 2007
The comment has been removedAnonymous
March 18, 2007
re: Do Entity Framework manages polimorphic query? Entity Framework queries can indeed handle polymorphic queries, in that you can query for a base type, derived type, etc. re: By the way, I'd like to have the EF use an NHibernate approach where mapping files are used as above, without cluttering the entity/value objects. With the Entity Framework, the mapping files all live on thier own, so there is no merging of mapping, store and objects. In additon, with a forthcoming release of the Entity Framework, we will be supporting the ability to use your own objects (not using our code gen) with the EF.Anonymous
March 21, 2007
I would also like that to use the POCO style from NHibernate with the Entity Framework. Thus that the entity classes have no dependency on the entity framework. So no specific base classes where you must derive from or .NET attributes. Implementing interfaces like INotifyPropertyChanged is no problem for me.Anonymous
March 21, 2007
How might one implement the entity framework from an ETL standpoint? Is that a valid idea at all? e.g. pre-ado.net data access layer...Anonymous
March 21, 2007
How might one implement the entity framework from an ETL standpoint? Is that a valid idea at all? e.g. pre-ado.net data access layer...Anonymous
March 26, 2007
Esta semana não foi tão animada quanto a semana passada.. ASP.Net Sébastien Just fez uma compilação dasAnonymous
April 02, 2007
I can't seem to get an Association/AssociationSet End Role in a .csdl file to work if the End Role type is derived from the EntitySet type. Is that even a possible scenario? The other part of that problem is that apparantly in the .msl file, I must include the mappings for all types derived from a base object within the base object's EntitySetMapping node. Otherwise I get an error stating that a particular TableMappingFragment is basically defined twice and could lead to data corruption. In other words, using the example .csdl at... http://blogs.msdn.com/adonet/archive/2007/02/12/entity-data-model-101-part-2.aspx ...how would you change the type of the End Role "ManagedEmployee" in Association "FK_Employee_Employee_ManagerID" from "Employee" to "SalesEmployee"? Thanks...Anonymous
April 02, 2007
Uhh..I think I found the answer which stinks if true. Again, from http://blogs.msdn.com/adonet/archive/2007/02/12/entity-data-model-101-part-2.aspx ... "Any associations using a derived type must be declared on the base type because the derived type does not declare an entity set in the entity container. The entity set is needed to define the scope of an association using the derived type." Please say it ain't so. To me, that seems like a severe limitation.Anonymous
April 02, 2007
Found more regarding derived type associations (relationships). I guess that functionality is being considered: http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=967167&SiteID=1 Sure would be nice if it gets included...Anonymous
March 01, 2008
It will be great to add a standard Parse() method to the database context's table properties to accept the ToString() value of an instance and do the query based on the configurations. Currently the developer needs to know which field to search for, i.e: dbContext.Publishers.Single(p => p.Name == "Wrox") this can be simplified as dbContext.Publishers.Parse("Wrox")Anonymous
May 31, 2008
One of the coolest features of the ADO.NET Entity Framework is the ability to use inheritance in your database! Very cool, but what does it mean, and why is it important? War of the worlds Relational The world of relational data is based around tuplesAnonymous
June 04, 2008
One of the coolest features of the ADO.NET Entity Framework is the ability to use inheritance in your database! Very cool, but what does it mean, and why is it important? War of the worlds Relational The world of relational data is based around tuplesAnonymous
July 15, 2008
A working example of Table per Hierarchy for Visual Studio 2008 SP1 is available at http://www.codeproject.com/KB/architecture/LinqEntityFramework.aspxAnonymous
September 03, 2008
Hi There, Good article on explanation of inheritance in entity framework.. I have a perticular sutuation where by , I have to inherit from a given entity solely for the purpose of adding more calculated fields .. and however DO NOT SAVE the inherited entity to database... for .e.g. I have an entity "Contractor" which contains.. "HourlyRate" and "EstimatedHours" and is working fine for saving these two values using entity framework... However, I now NEED TO DEFINE an INHERITED entity for reporting purpose.. "EstimatedCotractorCost" which will inherit from "Contractor" entity and will have a field "EstimatedCost" which should be "HourlyRate * EstimatedHours" ...and should not be serialised. how can i do that? Your help would be much appriciated. Hitesh.Anonymous
October 08, 2008
How could I change the type of an object since the condition, ProductType, is not mapped to a property? For instance: I would like to save a RegularProduct as a DiscontinuedProduct. It´s is possible? I´d appreciate if someone could answer this question. Thanks, RicardoAnonymous
December 03, 2008
The comment has been removedAnonymous
December 13, 2008
I'm not finding a full example of how to model Table Per Concrete Type anywhere. I suppose the basic dilemma is how one models the column mappings of the properties in the abstract base type that one defines in the conceptual model, since any given one of those properties will be sourced from multiple tables.Anonymous
May 14, 2009
SharePoint Create your own customized usage report solution step by step SharePoint WebPart PropertyAnonymous
August 10, 2009
The comment has been removedAnonymous
August 11, 2009
Why isn't there support to have one base-type that all Entities inherit from (EntityBase)? For example, if all my tables have a "ModifiedDate", why do I need to keep creating the same property over and over in all entity instances when they could just as easily inherit from one common base-type?