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

Polymorphic References

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 topic provides examples of how to configure polymorphic references by using the Fluent Mapping API.

What Are Polymorphic References?

Suppose, your class has the following structure:

public interface ISimpleInterface
{
}

public class ComplicatedClass
{
   public int Id{get;set;}
   public ISimpleInterface PointToDifferentTables{get;set;}
}

public class FirstDerivate : ISimpleInterface
{
   public int Id{get;set;}
}

public class SecondDerivate : ISimpleInterface
{
   public int Id{get;set;}
}

public class ThirdDerivate : ISimpleInterface
{
   public int Id{get;set;}
}
Public Interface ISimpleInterface
End Interface

Public Class ComplicatedClass
    Private _iD As Integer
    Public Property ID() As Integer
        Get
            Return _iD
        End Get
        Set(ByVal value As Integer)
            _iD = value
        End Set
    End Property
    Private _pointToDifferentTables As ISimpleInterface
    Public Property PointToDifferentTables() As ISimpleInterface
        Get
            Return _PointToDifferentTables
        End Get
        Set(ByVal value As ISimpleInterface)
            _PointToDifferentTables = value
        End Set
    End Property
End Class

Public Class FirstDerivate
    Implements ISimpleInterface
    Private _iD As Integer
    Public Property ID() As Integer
        Get
            Return _iD
        End Get
        Set(ByVal value As Integer)
            _iD = value
        End Set
    End Property
End Class

Public Class SecondDerivate
    Implements ISimpleInterface
    Private _iD As Integer
    Public Property ID() As Integer
        Get
            Return _iD
        End Get
        Set(ByVal value As Integer)
            _iD = value
        End Set
    End Property
End Class

Public Class ThirdDerivate
    Implements ISimpleInterface
    Private _iD As Integer
    Public Property ID() As Integer
        Get
            Return _iD
        End Get
        Set(ByVal value As Integer)
            _iD = value
        End Set
    End Property
End Class

The PointToDifferentTables property can retrieve an ISimpleInterface implementation. It is a polymorphic reference.

Polymorphic collections are not currently supported.

Mapping Polymorphic References

Basically, you get the same mapping capabilities for a regular foreign key association in the polymorphic API. The important moment here is to use the WithAvailable method to define the different possible types for the association.

To use the WithAvailable extension method, you have to use/import the Telerik.OpenAccess.Metadata.Fluent.Advanced namespace.

MappingConfiguration<ComplicatedClass> config = new MappingConfiguration<ComplicatedClass>();
config.MapType( x => new
{
   ID = x.Id
} ).ToTable( "ComplicatedTable" );
config.HasProperty( x => x.Id ).IsIdentity( KeyGenerator.Autoinc );

MappingConfiguration<FirstDerivate> firstDerivate = new MappingConfiguration<FirstDerivate>();
firstDerivate.MapType().ToTable("FirstDerivate");
firstDerivate.HasProperty(p => p.Id).IsIdentity();

MappingConfiguration<SecondDerivate> secondDerivate = new MappingConfiguration<SecondDerivate>();
secondDerivate.MapType().ToTable( "SecondDerivate" );
secondDerivate.HasProperty( p => p.Id ).IsIdentity();

MappingConfiguration<ThirdDerivate> thirdDerivate = new MappingConfiguration<ThirdDerivate>();
thirdDerivate.MapType().ToTable( "ThirdDerivate" );
thirdDerivate.HasProperty( p => p.Id ).IsIdentity();

config.HasAssociation( x => x.PointToDifferentTables )
   .WithAvailable( typeof( FirstDerivate ), "First" )
   .WithAvailable( typeof( SecondDerivate ), "Second" )
   .WithAvailable( typeof( ThirdDerivate ), "Third" )
   .WithDiscriminatingColumn( "Derivates" )
   .ToColumn( "PolymorphicReference" );
Dim config As New MappingConfiguration(Of ComplicatedClass)()
config.MapType(Function(x) New With {Key .ID = x.ID}).ToTable("ComplicatedTable")
config.HasProperty(Function(x) x.ID).IsIdentity(KeyGenerator.Autoinc)
config.FieldNamingRules.AddPrefix = "_"

Dim firstDerivate As New MappingConfiguration(Of FirstDerivate)()
firstDerivate.MapType().ToTable("FirstDerivate")
firstDerivate.HasProperty(Function(p) p.ID).IsIdentity()
firstDerivate.FieldNamingRules.AddPrefix = "_"

Dim secondDerivate As New MappingConfiguration(Of SecondDerivate)()
secondDerivate.MapType().ToTable("SecondDerivate")
secondDerivate.HasProperty(Function(p) p.ID).IsIdentity()
secondDerivate.FieldNamingRules.AddPrefix = "_"

Dim thirdDerivate As New MappingConfiguration(Of ThirdDerivate)()
thirdDerivate.MapType().ToTable("ThirdDerivate")
thirdDerivate.HasProperty(Function(p) p.ID).IsIdentity()
thirdDerivate.FieldNamingRules.AddPrefix = "_"

config.HasAssociation(Function(x) x.PointToDifferentTables).
    WithAvailable(GetType(FirstDerivate), "First").
    WithAvailable(GetType(SecondDerivate), "Second").
    WithAvailable(GetType(ThirdDerivate), "Third").
    WithDiscriminatingColumn("Derivates").
    ToColumn("PolymorphicReference")

The purpose of the discriminator column is to store information about the type of the referenced object. Its name can be controlled using WithDiscriminatingColumn(string) and the values stored are the values provided in the second argument of WithAvailable(type, string). You can skip defining a value and one will be automatically calculated for you. All types that implement the common interface also need to have a similar identity mechanism so the FK information can be stored in the same column(s).