Vertical Inheritance
This article is relevant to entity models that utilize the deprecated Visual Studio integration of Telerik Data Access. The current documentation of the Data Access framework is available here.
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 domain 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