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

Flat 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 flat inheritance mapping by using the Fluent Mapping API. With flat mapping, fields from the subclasses are mapped to a superclass table. Flat mapping is the simplest and is usually the fastest option so it is the default. In Flat mapping, the entire class hierarchy is persisted into a single table. That includes everything from an interface/abstract class at the top, all the way down to implementation classes at the bottom.

Modeling Flat Inheritance

The following example demonstrates how to model flat 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 class and the primary key is the AnimalId property. All derived classes (e.g. Cat and Dog) 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.

There are two important things that should be pointed out here: When you model Flat inheritance, all types should be mapped to the same table. Second, all derived types must have flat mapping explicitly specified.

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.Flat )
           .ToTable( "Animal" );

       MappingConfiguration<Cat> cat = new MappingConfiguration<Cat>();
       cat.MapType( x => new
                               {
                                   x.LivesLeft
                               } )
           .Inheritance( Telerik.OpenAccess.InheritanceStrategy.Flat )
           .ToTable( "Animal" );

       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.FieldNamingRules.AddPrefix = "_"
        animal.HasProperty(Function(x) x.AnimalId).IsIdentity(KeyGenerator.Autoinc)

        Dim dog As New MappingConfiguration(Of Dog)()
        dog.FieldNamingRules.AddPrefix = "_"
        dog.MapType(Function(x) New With {Key .BB = x.BestFriend}).
            Inheritance(Telerik.OpenAccess.InheritanceStrategy.Flat).
            ToTable("Animal")

        Dim cat As New MappingConfiguration(Of Cat)()
        cat.FieldNamingRules.AddPrefix = "_"
        cat.MapType(Function(x) New With {Key x.LivesLeft}).
            Inheritance(Telerik.OpenAccess.InheritanceStrategy.Flat).
            ToTable("Animal")

        configurations.Add(animal)
        configurations.Add(dog)
        configurations.Add(cat)

        Return configurations
    End Function
End Class

In Flat mapping, the entire class hierarchy is persisted to a single table. That includes everything from an interface/abstract class at the top, all the way down to implementation classes at the bottom. When you update your database schema to the latest model state, one table will be create - Animal.

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(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