In This Topic
LinqConnect supports two kinds of inheritance hierarchy: Table Per Hierarchy (TPH) and Table Per Type (TPT). This topic describes how to map both of these kinds.
TPH Classes
public class TphRoot
{
public int Id { get; set; }
public string Root_Value { get; set; }
public string Discriminator_Value { get; set; }
}
public class TphA : TphRoot
{
public byte[] A_Value { get; set; }
}
public class TphB : TphRoot
{
public DateTime B_Value { get; set; }
}
public class TphB1 : TphB
{
public char B1_Value { get; set; }
}
public class TphB2 : TphB
{
public TimeSpan B2_Value { get; set; }
}
Public Class TphRoot
Public Property Id As Integer
Public Property Root_Value As String
Public Property Discriminator_Value As String
End Class
Public Class TphA
Inherits TphRoot
Public Property A_Value As Byte()
End Class
Public Class TphB
Inherits TphRoot
Public Property B_Value As DateTime
End Class
Public Class TphB1
Inherits TphB
Public Property B1_Value As Char
End Class
Public Class TphB2
Inherits TphB
Public Property B2_Value As TimeSpan
End Class
TPT Classes
public class TptRoot
{
public int Id { get; set; }
public string Root_Value { get; set; }
}
public class TptA : TptRoot
{
public string A_Value { get; set; }
}
public class TptB : TptRoot
{
public string B_Value { get; set; }
}
public class TptB1 : TptB
{
public string B1_Value { get; set; }
}
public class TptB2 : TptB
{
public string B2_Value { get; set; }
}
Public Class TptRoot
Public Property Id As Integer
Public Property Root_Value As String
End Class
Public Class TptA
Inherits TptRoot
Public Property A_Value As String
End Class
Public Class TptB
Inherits TptRoot
Public Property B_Value As String
End Class
Public Class TptB1
Inherits TptB
Public Property B1_Value As String
End Class
Public Class TptB2
Inherits TptB
Public Property B2_Value As String
End Class
Attribute Mapping
When using attribute mapping, inheritance relationship is specified with the InheritanceMapping and InheritanceColumnMapping attributes. This attributes have the following properties.
You shoud use InheritanceMapping attribute to specify all the hierarchy types on the root class. For TPT hierarchy, the root type can be omitted.
InheritanceColumnMapping attribute is used for TPT hierarchies. It specifies the correspondence between the primary key columns of the base and derived entity classes.
InheritanceMapping attribute properties:
Property |
Type |
Description |
Code |
String |
The discriminator column should have the specified Code value to be an instance of this class.
|
Type |
Type |
Type of the entity class, mapped to the table.
|
IsDefault |
Boolean |
Determines whether the specified type is the default type of the hierarchy. If the discriminator column has a value that dows not correspond to any of the hierarchy discriminator values, this row is considered to be an instance of the default hierarchy class.
|
InheritanceColumnMapping attribute is used for TPT hierarchies. It specifies the correspondence between the primary key columns of the base and derived entity classes.
InheritanceColumnMapping attribute properties:
Property |
Type |
Description |
BaseColumnName |
String |
Type of the entity class, mapped to the table.
|
ColumnName |
String |
Determines whether the specified type is the default type of the hierarchy. If the discriminator column has the value that dows not correspond to any of the hierarchy discriminator values, this row is considered to be an instance of the default hierarchy class.
|
TPH Mapping
[Table(Name = "TPH_TABLE")]
[InheritanceMapping(Code = "R", Type = typeof(TphRoot), IsDefault = true)]
[InheritanceMapping(Code = "A", Type = typeof(TphA))]
[InheritanceMapping(Code = "B", Type = typeof(TphB))]
[InheritanceMapping(Code = "B1", Type = typeof(TphB1))]
[InheritanceMapping(Code = "B2", Type = typeof(TphB2))]
public class TphRoot
{
[Column(Name = "ID", IsPrimaryKey = true)]
public int Id { get; set; }
[Column]
public string Root_Value { get; set; }
[Column(IsDiscriminator = true, CanBeNull = false)]
public string Discriminator_Value { get; set; }
}
public class TphA : TphRoot
{
[Column]
public byte[] A_Value { get; set; }
}
public class TphB : TphRoot
{
[Column]
public DateTime B_Value { get; set; }
}
public class TphB1 : TphB
{
[Column]
public char B1_Value { get; set; }
}
public class TphB2 : TphB
{
[Column]
public TimeSpan B2_Value { get; set; }
}
<Table(Name:="TPH_TABLE")> _
<InheritanceMapping(Code:="R", Type:=GetType(TphRoot), IsDefault:=True)> _
<InheritanceMapping(Code:="A", Type:=GetType(TphA))> _
<InheritanceMapping(Code:="B", Type:=GetType(TphB))> _
<InheritanceMapping(Code:="B1", Type:=GetType(TphB1))> _
<InheritanceMapping(Code:="B2", Type:=GetType(TphB2))> _
Public Class TphRoot
<Column(Name:="ID", IsPrimaryKey:=True)> _
Public Property Id As Integer
<Column()> _
Public Property Root_Value As String
<Column(IsDiscriminator:=True, CanBeNull:=False)> _
Public Property Discriminator_Value As String
End Class
Public Class TphA
Inherits TphRoot
<Column()> _
Public Property A_Value As Byte()
End Class
Public Class TphB
Inherits TphRoot
<Column()> _
Public Property B_Value As DateTime
End Class
Public Class TphB1
Inherits TphB
<Column()> _
Public Property B1_Value As Char
End Class
Public Class TphB2
Inherits TphB
<Column()> _
Public Property B2_Value As TimeSpan
End Class
TPT Mapping
[Table(Name = "TPT_ROOT")]
[InheritanceMapping(Type = typeof(TptA))]
[InheritanceMapping(Type = typeof(TptB))]
[InheritanceMapping(Type = typeof(TptB1))]
[InheritanceMapping(Type = typeof(TptB2))]
public class TptRoot
{
[Column(Name = "ID", IsPrimaryKey = true)]
public int Id { get; set; }
[Column]
public string Root_Value { get; set; }
}
[Table(Name = "TPT_A")]
[InheritanceColumnMapping(BaseColumnName = "ID", ThisColumnName = "A_ID")]
public class TptA : TptRoot
{
[Column]
public string A_Value { get; set; }
}
[Table(Name = "TPT_B")]
[InheritanceColumnMapping(BaseColumnName = "ID", ThisColumnName = "B_ID")]
public class TptB : TptRoot
{
[Column]
public string B_Value { get; set; }
}
[Table(Name = "TPT_B1")]
[InheritanceColumnMapping(BaseColumnName = "ID", ThisColumnName = "B1_ID")]
public class TptB1 : TptB
{
[Column]
public string B1_Value { get; set; }
}
[Table(Name = "TPT_B2")]
[InheritanceColumnMapping(BaseColumnName = "ID", ThisColumnName = "B2_ID")]
public class TptB2 : TptB
{
[Column]
public string B2_Value { get; set; }
}
[Table(Name = "TPT_ROOT")]
[InheritanceMapping(Type = typeof(TptA))]
[InheritanceMapping(Type = typeof(TptB))]
[InheritanceMapping(Type = typeof(TptB1))]
[InheritanceMapping(Type = typeof(TptB2))]
public class TptRoot
{
[Column(Name = "ID", IsPrimaryKey = true)]
public int Id { get; set; }
[Column]
public string Root_Value { get; set; }
}
[Table(Name = "TPT_A")]
[InheritanceColumnMapping(BaseColumnName = "ID", ThisColumnName = "A_ID")]
public class TptA : TptRoot
{
[Column]
public string A_Value { get; set; }
}
[Table(Name = "TPT_B")]
[InheritanceColumnMapping(BaseColumnName = "ID", ThisColumnName = "B_ID")]
public class TptB : TptRoot
{
[Column]
public string B_Value { get; set; }
}
[Table(Name = "TPT_B1")]
[InheritanceColumnMapping(BaseColumnName = "ID", ThisColumnName = "B1_ID")]
public class TptB1 : TptB
{
[Column]
public string B1_Value { get; set; }
}
[Table(Name = "TPT_B2")]
[InheritanceColumnMapping(BaseColumnName = "ID", ThisColumnName = "B2_ID")]
public class TptB2 : TptB
{
[Column]
public string B2_Value { get; set; }
}
XML Mapping
Inheritance hierarchies are mapped with the Type tag and InheritanceCode and IsInheritanceDefault attributes. The IsDiscriminator attribute of the Column tag specifies the discriminator column.
InheritanceCode attribute contains the value the discriminator column should have for a row to be an instance of this class. IsInheritanceDefault determines whether the class is the default type of the hierarchy. If the discriminator column has a value that dows not correspond to any of the hierarchy discriminator values, this row is considered to be an instance of the default hierarchy class.
TPH Mapping
<Table Name="TPH_TABLE">
<Type Name="TphRoot" InheritanceCode="R" IsInheritanceDefault="true">
<Column Name="ID" Member="Id" IsPrimaryKey="true" />
<Column Member="Root_Value" />
<Column Member="Discriminator_Value" CanBeNull="false" IsDiscriminator="true" />
<Type Name="TphA" InheritanceCode="A">
<Column Member="A_Value" />
</Type>
<Type Name="TphB" InheritanceCode="B">
<Column Member="B_Value" />
<Type Name="TphB1" InheritanceCode="B1">
<Column Member="B1_Value" />
</Type>
<Type Name="TphB2" InheritanceCode="B2">
<Column Member="B2_Value" />
</Type>
</Type>
</Type>
</Table>
TPT Mapping
<Table>
<Type Name="TptRoot" TableName="TPT_ROOT">
<Column Name="ID" Member="Id" IsPrimaryKey="true" />
<Column Member="Root_Value" />
<Type Name="TptA" TableName="TPT_A">
<InheritanceColumn ThisName="A_ID" BaseName="ID" />
<Column Member="A_Value" />
</Type>
<Type Name="TptB" TableName="TPT_B">
<InheritanceColumn ThisName="B_ID" BaseName="ID" />
<Column Member="B_Value" />
<Type Name="TptB1" TableName="TPT_B1">
<InheritanceColumn ThisName="B1_ID" BaseName="ID" />
<Column Member="B1_Value" />
</Type>
<Type Name="TptB2" TableName="TPT_B2">
<InheritanceColumn ThisName="B2_ID" BaseName="ID" />
<Column Member="B2_Value" />
</Type>
</Type>
</Type>
</Table>
Fluent Mapping
FluentMappingBuilder class methods are used for mapping inheritance hierarchies.
TPH Mapping
FluentMappingBuilder builder = new FluentMappingBuilder(null);
// TphRoot
builder.Entity<TphRoot>()
.FullTableName("TPH_TABLE")
.PrimaryKey(p => p.Id);
// Table Per Hierarchy (TPH) inheritance:
builder.Entity<TphRoot>()
.Map()
.Discriminator(p => p.Discriminator_Value)
.DiscriminatorValue("R")
.IsInheritanceDefault()
.MapChild<TphA>()
.DiscriminatorValue("A")
.MapChild<TphB>()
.DiscriminatorValue("B")
.MapChild<TphB1>()
.DiscriminatorValue("B1")
.MapChild<TphB2>()
.DiscriminatorValue("B2");
// Properties:
builder.Entity<TphRoot>()
.Property(p => p.Id)
.ColumnName("ID");
builder.Entity<TphRoot>()
.Property(p => p.Discriminator_Value)
.NotNullable();
// TphA
builder.Entity<TphA>()
.Property(p => p.A_Value);
// TphB
builder.Entity<TphB>()
.Property(p => p.B_Value);
// TphB1
builder.Entity<TphB1>()
.Property(p => p.B1_Value);
// TphB2
builder.Entity<TphB2>()
.Property(p => p.B2_Value);
Dim builder As New FluentMappingBuilder(Nothing)
' TphRoot
builder.Entity(Of TphRoot)() _
.FullTableName("TPH_TABLE") _
.PrimaryKey(Function(p) p.Id)
' Table Per Hierarchy (TPH) inheritance:
builder.Entity(Of TphRoot) _
.Map() _
.Discriminator(Function(p) p.Discriminator_Value) _
.DiscriminatorValue("R") _
.IsInheritanceDefault() _
.MapChild(Of TphA) _
.DiscriminatorValue("A") _
.MapChild(Of TphB) _
.DiscriminatorValue("B") _
.MapChild(Of TphB1) _
.DiscriminatorValue("B1") _
.MapChild(Of TphB2) _
.DiscriminatorValue("B2")
' Properties:
builder.Entity(Of TphRoot) _
.Property(Function(p) p.Id) _
.ColumnName("ID")
builder.Entity(Of TphRoot) _
.Property(Function(p) p.Discriminator_Value) _
.NotNullable()
' TphA
builder.Entity(Of TphA) _
.Property(Function(p) p.A_Value)
' TphB
builder.Entity(Of TphB) _
.Property(Function(p) p.B_Value)
' TphB1
builder.Entity(Of TphB1) _
.Property(Function(p) p.B1_Value)
' TphB2
builder.Entity(Of TphB2) _
.Property(Function(p) p.B2_Value)
TPT Mapping
FluentMappingBuilder builder = new FluentMappingBuilder(null);
// TptRoot
// Table Per Type (TPT) inheritance:
builder.Entity<TptRoot>()
.FullTableName("TPT_ROOT")
.PrimaryKey(p => p.Id);
builder.Entity<TptA>()
.FullTableName("TPT_A")
.Map(p => new { A_ID = p.Id });
builder.Entity<TptB>()
.FullTableName("TPT_B")
.Map(p => new { B_ID = p.Id });
builder.Entity<TptB1>()
.FullTableName("TPT_B1")
.Map(p => new { B1_ID = p.Id });
builder.Entity<TptB2>()
.FullTableName("TPT_B2")
.Map(p => new { B2_ID = p.Id });
// Properties:
builder.Entity<TptRoot>()
.Property(p => p.Id)
.ColumnName("ID");
builder.Entity<TptRoot>()
.Property(p => p.Root_Value);
// TptA
builder.Entity<TptA>()
.Property(p => p.A_Value);
// TptB
builder.Entity<TptB>()
.Property(p => p.B_Value);
// TptB1
builder.Entity<TptB1>()
.Property(p => p.B1_Value);
// TptB2
builder.Entity<TptB2>()
.Property(p => p.B2_Value);
Dim builder As New FluentMappingBuilder(Nothing)
' TptRoot
' Table Per Type (TPT) inheritance:
builder.Entity(Of TptRoot) _
.FullTableName("TPT_ROOT") _
.PrimaryKey(Function(p) p.Id)
builder.Entity(Of TptA)() _
.FullTableName("TPT_A") _
.Map(Function(p) New With {.A_ID = p.Id})
builder.Entity(Of TptB) _
.FullTableName("TPT_B") _
.Map(Function(p) New With {.B_ID = p.Id})
builder.Entity(Of TptB1) _
.FullTableName("TPT_B1") _
.Map(Function(p) New With {.B1_ID = p.Id})
builder.Entity(Of TptB2) _
.FullTableName("TPT_B2") _
.Map(Function(p) New With {.B2_ID = p.Id})
' Properties:
builder.Entity(Of TptRoot) _
.Property(Function(p) p.Id) _
.ColumnName("ID")
builder.Entity(Of TptRoot) _
.Property(Function(p) p.Root_Value)
' TptA
builder.Entity(Of TptA) _
.Property(Function(p) p.A_Value)
' TptB
builder.Entity(Of TptB) _
.Property(Function(p) p.B_Value)
' TptB1
builder.Entity(Of TptB1) _
.Property(Function(p) p.B1_Value)
' TptB2
builder.Entity(Of TptB2) _
.Property(Function(p) p.B2_Value)