Class table inheritance in LightSpeed

As we’ve discussed before, one of the big impedance mismatches between the object and relational worlds is over inheritance. Inheritance is a tremendously useful concept in object-oriented programming, but relational databases don’t have that concept at all, and need to have inheritance relationships represented in a different way. There are three common patterns for representing inheritance hierarchies, which we refer to as concrete table inheritance, single table inheritance and class table inheritance.

In the past, LightSpeed has supported only concrete and single table inheritance. We know a number of customers have been keen to see class table inheritance added to the list, and we’re pleased to announce that current nightly builds of LightSpeed include support for class table inheritance.

What is class table inheritance?

Class table inheritance represents each class in a hierarchy with a table. Unlike concrete table inheritance, however, each table includes columns only for the properties introduced at that level of the hierarchy (plus the mandatory Id column which allows rows in the different tables to be identified as referring to the same entity).

The benefit of class table inheritance is that it reduces duplication of column definitions: for example, a Name column appears only in the Person table, rather than having to appear in each of the Person, Employee and Manager tables. The disadvantage of class table inheritance is that it requires a join across all the tables in the hierarchy: to load a Manager requires you to access each of the Person, Employee and Manager tables and to combine the results.

How can I use class table inheritance in LightSpeed?

First, you need to tell LightSpeed that you want to map the inheritance hierarchy to the database using class table inheritance instead of single or concrete table inheritance.

  • To specify class table inheritance in the designer, select the inheritance arrow and set the Inheritance Type to ClassTableInheritance. You’ll need to do this at each level of the hierarchy.
  • To specify class table inheritance in code, apply the new InheritanceMappingAttribute to the root class of the hierarchy, specifying InheritanceMappingKind.ClassTableInheritance.

Second, you need to specify a discriminator. This allows LightSpeed to know what kind of entity each row represents. The table for the root entity type must contain the discriminator column. Discriminators work in exactly the same way as in single table inheritance:

  • To specify a discriminator in the designer, select the inheritance arrow and set the Discriminator Name, Discriminator Type and Discriminator Value.
  • To specify a discriminator in code, apply the DiscriminatorAttribute to the derived class.

By the way, the designer supports creating tables for class table inheritance mappings, so rather than building the tables by hand, you can create your inheritance hierarchy in the designer, set up the inheritance relations to be class table inheritance, and use the Update Database command to create the tables with all the right columns.

When should I use class table inheritance in LightSpeed?

Class table inheritance is a good fit when you need polymorphism, but have a lot of columns that make sense only for child entities.

If you don’t need polymorphism, concrete table inheritance gives you better performance because it avoids the need to join over every table in the hierarchy.

If you need polymorphism but your derived classes don’t introduce extra state (only behaviour), or only a little extra state, single table inheritance provides polymorphism and again avoids the performance penalty of the join.

In particular, the join cost may be prohibitive if you have a very deep or wide hierarchy: every table in the hierarchy participates in the join, which can be costly if there are a large number of tables.

Where can I get it?

Class table inheritance is included in current nightly builds of LightSpeed. You can get download LightSpeed Express edition for free, or if you’re a retail customer you can get the latest build from the store. Class table inheritance is in beta right now so if you run into any problems please let us know on the forums. Check it out!

Tagged as LightSpeed

6 Responses to “Class table inheritance in LightSpeed”

  • Great step forward!
    However, what if a Player is both a Footballer AND a Cricketer and I want to maintain a single Player record? Shouldn’t it be the responsability of the descendant class to decide which player to load?

  • Unfortunately, C# and Visual Basic don’t have a good way of modelling that situation anyway. Because they lack multiple inheritance, the class hierarchy can’t even express the concept of a FootballingCricketer. It’s therefore a bit moot to try to support it at the ORM level.

    If you needed something like that, I think .NET single inheritance would force you to express it as something like a Player entity with a PlayedGameInfos collection. PlayedGameInfo could then be a polymorphic hierarchy with subclasses like FootballingInfo, CricketingInfo, etc. (and these could be modelled using class table inheritance). Not as nice as multiple inheritance, but the best I can think of given the limitations of the CLR and the C# and VB languages.

  • Jeremy directed me to this post, but I’m having a problem where my base entity is hierarchical (i.e. self referencing). Lightspeed is getting upset about derived classes which inherit this self-association, complaining that “circular references are not supported”. Any ideas?

  • Mark, this is working okay for me. I think we did have a bug with this a while back but it should be fixed in 3.11 or the latest nightly. If updating doesn’t fix the problem, could you post a repro project in the LightSpeed support forum? Thanks!

  • I agree with what Diego said, I would expect that the discriminator columns would not be required either, more so when the base class is generated as abstract… In deed, they’re not part of Mr Fowlers’ pattern. The child type should instead be worked out by the existence of a row in the child table with the same primary key value as the parent’s primary key.

    As Diego mentions, I think the responsibility of the type casting would be upon the caller and would only be accessible up the inheritance hierarchy anyways. For example, I wouldn’t expect to be able to load a Cricketer object and have it be able to be cast as a Footballer. However, what I would like to be able to do is create a Footballer and take his common properties (from Player) and consume them in a new instance of Cricketer. I don’t think that would involve any multiple inheritance to do so.

    My two cents.

  • Hi Andrew,

    Regarding automatically figuring out entity type by the presence of rows in the child tables: this is an interesting idea — thanks for the suggestion! Unfortunately it is not practical for us to implement it (it also rules out some optimisations that we’d like to be able to support in the future).

    Regarding the CricketingFootballer, having two objects (a Cricketer and a Footballer) representing the same entity (a CricketingFootballer) makes for very confusing equality/identity semantics. (Not to mention the potential errors when you modify the Footballer.Name to one thing and the Cricketer.Name to another.) You can however do something like this by using composition rather than inheritance to model the Player-Cricketer relationship, e.g. via a one-to-one relationship.

  • Leave a Reply

Archives

Join our mailer

You should join our newsletter! Sent monthly:

Back to Top