LinqConnect Documentation
Complex Type Mapping

Complex types, used as class member types, can have common mapping for all classes in the model and custom mappings for some class. Common mapping is used by all classes having properties of this type by default, however you can define custom mapping for a class, which will override the default one. Thus, one complex type class may have different mappings for each entity class.

Let's use the following sample classes to demonstrate complex type mapping.


C#csharpCopy Code
public class Company {
    public int Id { get; set; }
    public AddressType Address { get; set; }
    // ...
}
 
public class Contact {
    public int Id { get; set; }
    public AddressType Address { get; set; }
    // ...
}
 
public class AddressType {
    public string Country { get; set; }
    public string City { get; set; }
    public string Street { get; set; }
    public string Zip { get; set; }
}
Visual BasicCopy Code
Public Class Company
    Public Property Id As Integer
    Public Property Address As AddressType
    '...
End Class

Public Class Contact
    Public Property Id As Integer
    Public Property Address As AddressType
    '...
End Class

Public Class AddressType
    Public Property Country As String
    Public Property City As String
    Public Property Street As String
    Public Property Zip As String
End Class

In this sample we will create common mapping for the AddressType class. The Company class will use the default common mapping of AddressType, and the Contact class will have its own specific mapping for it.

Attribute Mapping

When using attribute mapping, the ValueTypeProperty attribute should be specified for complex type properties. The properties of a complex type class are mapped with the Column attribute.


C#csharpCopy Code
[Table]
public class Company {
 
    [Column(IsPrimaryKey=true)]
    public int Id { get; set; }
 
    [ValueTypeProperty]
    public AddressType Address { get; set; }
 
    // ...
}
 
[Table]
public class Contact {
 
    [Column(IsPrimaryKey = true)]
    public int Id { get; set; }
 
    [ValueTypeProperty]
    [Column(Member="Country", Name="COUNTRY", CanBeNull=false, DbType="VARCHAR2(400) NOT NULL")]
    [Column(Member="City", Name="CITY", CanBeNull=false, DbType="VARCHAR2(400) NOT NULL")]
    [Column(Member="Street", Name="STREET", CanBeNull=false, DbType="CLOB NOT NULL")]
    [Column(Member="Zip", Name="ZIP", CanBeNull=false, DbType="VARCHAR2(400) NOT NULL")]
    public AddressType Address { get; set; }
 
    // ...
}
 
public class AddressType {
 
    [Column(CanBeNull=false, DbType="VARCHAR2(400) NOT NULL")]
    public string Country { get; set; }
 
    [Column(CanBeNull=false, DbType="VARCHAR2(400) NOT NULL")]
    public string City { get; set; }
 
    [Column(CanBeNull=false, DbType="VARCHAR2(400) NOT NULL")]
    public string Street { get; set; }
 
    [Column(CanBeNull=false, DbType="VARCHAR2(40) NOT NULL")]
    public string Zip { get; set; }
}
Visual BasicCopy Code
    <Table()> _
Public Class Company

    <Column(IsPrimaryKey:=True)> _
Public Property Id As Integer

    <ValueTypeProperty()> _
    Public Property Address As AddressType

    '...
End Class

<Table()>
Public Class Contact

    <Column(IsPrimaryKey:=True)> _
    Public Property Id As Integer

    <ValueTypeProperty()> _
    <Column(Member:="Country", Name:="COUNTRY", CanBeNull:=False, DbType:="VARCHAR2(400) NOT NULL")> _
    <Column(Member:="City", Name:="CITY", CanBeNull:=False, DbType:="VARCHAR2(400) NOT NULL")> _
    <Column(Member:="Street", Name:="STREET", CanBeNull:=False, DbType:="CLOB NOT NULL")> _
    <Column(Member:="Zip", Name:="ZIP", CanBeNull:=False, DbType:="VARCHAR2(400) NOT NULL")> _
    Public Property Address As AddressType

    '...
End Class

Public Class AddressType

    <Column(CanBeNull:=False, DbType:="VARCHAR2(400) NOT NULL")> _
    Public Property Country As String

    <Column(CanBeNull:=False, DbType:="VARCHAR2(400) NOT NULL")> _
    Public Property City As String

    <Column(CanBeNull:=False, DbType:="VARCHAR2(400) NOT NULL")> _
    Public Property Street As String

    <Column(CanBeNull:=False, DbType:="VARCHAR2(40) NOT NULL")> _
    Public Property Zip As String

End Class

XML Mapping

Database tag is used for DataContext XML mapping. Its Name attribute defines the schema name and the Provider attribute defines the Provider.

<Database ...>
  <Table>
    <Type Name="Company">
      <Column Member="Id" IsPrimaryKey="true" />
      <Column Member="Address" Type="AddressType" IsValueType="True" />
      ...
    </Type>
  </Table>
  <Table>
    <Type Name="Contact">
      <Column Member="Id" IsPrimaryKey="true" />
      <Column Member="Address" Type="AddressType" IsValueType="True">
        <TypeMapping>
          <Column Name="COUNTRY" Member="Country" CanBeNull="false" DbType="VARCHAR2(400) NOT NULL" />
          <Column Name="CITY" Member="City" CanBeNull="false" DbType="VARCHAR2(400) NOT NULL" />
          <Column Name="STREET" Member="Street" CanBeNull="false" DbType="CLOB NOT NULL" />
          <Column Name="ZIP" Member="Zip" CanBeNull="false" DbType="VARCHAR2(40) NOT NULL" />
        </TypeMapping>
      </Column>
      ...
    </Type>
  </Table>
  <Type Name="AddressType">
    <Column Name="Country" Member="Country" CanBeNull="false" DbType="VARCHAR2(400) NOT NULL" />
    <Column Name="City" Member="City" CanBeNull="false" DbType="VARCHAR2(400) NOT NULL" />
    <Column Name="Street" Member="Street" CanBeNull="false" DbType="VARCHAR2(400) NOT NULL" />
    <Column Name="Zip" Member="Zip" CanBeNull="false" DbType="VARCHAR2(40) NOT NULL" />
  </Type>
  ...
</Database>

Fluent Mapping

FluentMappingBuilder class methods are used for mapping complex types.


C#csharpCopy Code
FluentMappingBuilder builder = new FluentMappingBuilder(null);

// Company mapping
builder.Entity<Company>()
    .PrimaryKey(p => p.Id);

// Contact mapping
builder.Entity<Contact>()
    .PrimaryKey(p => p.Id);
builder.Entity<Contact>()
    .Property(p => p.Address.Country)
        .ColumnName("COUNTRY")
        .NotNullable()
        .ServerDataType("VARCHAR2(400) NOT NULL");
builder.Entity<Contact>()
    .Property(p => p.Address.City)
        .ColumnName("CITY")
        .NotNullable()
        .ServerDataType("VARCHAR2(400) NOT NULL");
builder.Entity<Contact>()
    .Property(p => p.Address.Street)
        .ColumnName("STREET")
        .NotNullable()
        .ServerDataType("CLOB NOT NULL");
builder.Entity<Contact>()
    .Property(p => p.Address.Zip)
        .ColumnName("ZIP")
        .NotNullable()
        .ServerDataType("VARCHAR2(40) NOT NULL");

// Complex type mapping:
builder.ComplexType<AddressType>()
    .Property(p => p.Country)
        .NotNullable()
        .ServerDataType("VARCHAR2(400) NOT NULL");
builder.ComplexType<AddressType>()
    .Property(p => p.City)
        .NotNullable()
        .ServerDataType("VARCHAR2(400) NOT NULL");
builder.ComplexType<AddressType>()
    .Property(p => p.Street)
        .NotNullable()
        .ServerDataType("VARCHAR2(400) NOT NULL");
builder.ComplexType<AddressType>()
    .Property(p => p.Zip)
        .ColumnName("Zip")
        .NotNullable()
        .ServerDataType("VARCHAR2(40) NOT NULL");
Visual BasicCopy Code
Dim builder As New FluentMappingBuilder(Nothing)
 
' Company mapping
builder.Entity(Of Company) _
    .PrimaryKey(Function(p) p.Id)

' Contact mapping
builder.Entity(Of Contact)() _
    .PrimaryKey(Function(p) p.Id)
builder.Entity(Of Contact)() _
    .Property(Function(p) p.Address.Country) _
        .ColumnName("COUNTRY") _
        .NotNullable() _
        .ServerDataType("VARCHAR2(400) NOT NULL")
builder.Entity(Of Contact)() _
    .Property(Function(p) p.Address.City) _
        .ColumnName("CITY") _
        .NotNullable() _
        .ServerDataType("VARCHAR2(400) NOT NULL")
builder.Entity(Of Contact)() _
    .Property(Function(p) p.Address.Street) _
        .ColumnName("STREET") _
        .NotNullable() _
        .ServerDataType("CLOB NOT NULL")
builder.Entity(Of Contact)() _
    .Property(Function(p) p.Address.Zip) _
        .ColumnName("ZIP") _
        .NotNullable() _
        .ServerDataType("VARCHAR2(40) NOT NULL")

' Complex type mapping:
builder.ComplexType(Of AddressType) _
    .Property(Function(p) p.Country) _
        .NotNullable() _
        .ServerDataType("VARCHAR2(400) NOT NULL")
builder.ComplexType(Of AddressType) _
    .Property(Function(p) p.City) _
        .NotNullable() _
        .ServerDataType("VARCHAR2(400) NOT NULL")
builder.ComplexType(Of AddressType) _
    .Property(Function(p) p.Street) _
        .NotNullable() _
        .ServerDataType("VARCHAR2(400) NOT NULL")
builder.ComplexType(Of AddressType) _
    .Property(Function(p) p.Zip) _
        .ColumnName("Zip") _
        .NotNullable() _
        .ServerDataType("VARCHAR2(40) NOT NULL")
End Sub

For more information see the ComplexConfiguration and ComplexConfiguration<TClass> Classes