Data Access has been discontinued. Please refer to this page for more information.

Vertical Inheritance

This tutorial teaches you how to model vertical inheritance mapping by using the Fluent Mapping API. With vertical mapping each class has its own table containing only its fields. That strategy is also known as "table-per-concrete-class" model. Each concrete persistent class in the model is persisted to its own table. For example, a Customer object is stored in the Customers table.

Modeling Vertical Inheritance

The following example demonstrates how to model vertical inheritance for the Animal hierarchy. The specific point here is that you have to specify a primary key only for the root class in the hierarchy. In this case, this is the Animal type and the primary key is the AnimalId property. All derived classes will use the primary key of the base (root) class. Take a look at the way the inheritance strategy is specified. You need to specify it by using the Inheritance method for each of the derived types (e.g. Cat and Dog).

When implementing vertical inheritance mapping, you have to specify a primary key only for the root class of the hierarchy, e.g. Animal.

public class FluentModelMetadataSource : FluentMetadataSource
{
   protected override IList<MappingConfiguration> PrepareMapping()
   {
       List<MappingConfiguration> configurations = new List<MappingConfiguration>();
       MappingConfiguration<Animal> animal = new MappingConfiguration<Animal>();
       animal.MapType().ToTable( "Animal" );
       animal.HasProperty( x => x.AnimalId ).IsIdentity( KeyGenerator.Autoinc );
       MappingConfiguration<Dog> dog = new MappingConfiguration<Dog>();
       dog.MapType( x => new
                               {
                                   BB = x.BestFriend
                               } )
           .Inheritance( Telerik.OpenAccess.InheritanceStrategy.Vertical )
           .ToTable( "Dog" );
       MappingConfiguration<Cat> cat = new MappingConfiguration<Cat>();
       cat.MapType( x => new
                               {
                                   LL = x.LivesLeft
                               } )
           .Inheritance( Telerik.OpenAccess.InheritanceStrategy.Vertical )
           .ToTable( "Cat" );
       configurations.Add( animal );
       configurations.Add( dog );
       configurations.Add( cat );
       return configurations;
   }
}
Public Class FluentModelMetadataSource
    Inherits FluentMetadataSource
    Protected Overrides Function PrepareMapping() As _
        System.Collections.Generic.IList(Of Telerik.OpenAccess.Metadata.Fluent.MappingConfiguration)
        Dim configurations As List(Of MappingConfiguration) = New List(Of MappingConfiguration)()
        Dim animal As New MappingConfiguration(Of Animal)()
        animal.MapType().ToTable("Animal")
        animal.HasProperty(Function(x) x.AnimalId).IsIdentity(KeyGenerator.Autoinc)
        animal.FieldNamingRules.AddPrefix = "_"
        Dim dog As New MappingConfiguration(Of Dog)()
        dog.FieldNamingRules.AddPrefix = "_"
        dog.MapType(Function(x) New With {Key .BB = x.BestFriend}).
            Inheritance(InheritanceStrategy.Vertical).ToTable("Dog")
        Dim cat As New MappingConfiguration(Of Cat)()
        cat.FieldNamingRules.AddPrefix = "_"
        cat.MapType(Function(x) New With {Key x.LivesLeft}).
            Inheritance(InheritanceStrategy.Vertical).ToTable("Cat")
        configurations.Add(animal)
        configurations.Add(dog)
        configurations.Add(cat)
        Return configurations
    End Function
End Class

When you update your database schema to the latest model state, three tables will be created - Animal, Cat and Dog.

If you take a look at the Animal table, you will see one additional column named voa_class. This is the discriminator column. Normally a discriminator column is required for flat and vertical inheritance. The discriminator column used to identify the type of each row with flat and vertical mapping is normally mapped to a SQL INTEGER but this can be changed. The default name for the discriminator column is voa_class. The name of the discriminator column can be changed, too. For more information, take a look at How to: Set Advanced Properties.

Animal Class

public class Animal
{
   public int AnimalId { get; set; }
   public string Name {get;set;}
   public int Age {get;set;}
}
Public Class Animal
    Private _animalId As Integer
    Public Property AnimalId As Integer
        Get
            Return _animalId
        End Get
        Set(value As Integer)
            _animalId = value
        End Set
    End Property
    Private _name As String
    Public Property Name() As String
        Get
            Return _name
        End Get
        Set(ByVal value As String)
            _name = value
        End Set
    End Property
    Private _age As Integer
    Public Property Age() As Integer
        Get
            Return _age
        End Get
        Set(ByVal value As Integer)
            _age = value
        End Set
    End Property
End Class

Dog Class

public class Dog : Animal
{
   public string BestFriend {get;set;}
}
Public Class Dog
    Inherits Animal
    Private _bestFriend As String
    Public Property BestFriend() As String
        Get
            Return _bestFriend
        End Get
        Set(ByVal value As String)
            _bestFriend = value
        End Set
    End Property
End Class

Cat Class

public class Cat : Animal
{
   public int LivesLeft {get;set;}
}
Public Class Cat
    Inherits Animal
    Private _livesLeft As Integer
    Public Property LivesLeft() As Integer
        Get
            Return _livesLeft
        End Get
        Set(ByVal value As Integer)
            _livesLeft = value
        End Set
    End Property
End Class

See Also