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

One-to-Many Associations

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 illustrates how to configure one-to-many associations.

If you want to learn how to create artificial associations between artificial types and real CLR types, please refer to the Artificial Associations section.

One-to-Many Associations

To define an one-to-many association, you have to define both of the navigation ends. The following example demonstrates how to create an one-to-many association between the Product and the Category classes. Note that first you should use the WithOpposite method and after that create a constraint via the HasConstraint method. The WithOpposite method specifies the inverse property of the relation. The HasConstraint method specifies the constraint that defines the relation and its endpoints. Sample FluentMetadataSource implementation could be found at the end of the topic.

When you define mapping for a collection property, the HasAssociation property expects the type of the property to be IList<T>. Note that in this example, the Products property in the Category class is of type IList<Product>.

productConfiguration.
   HasAssociation( p => p.Category ).
   WithOpposite( c => c.Products ).
   HasConstraint( ( p, c ) => p.CategoryId == c.Id );
productConfiguration.
    HasAssociation(Function(p) p.Category).
    WithOpposite(Function(c) c.Products).
    HasConstraint(Function(p, c) p.CategoryId = c.Id)

One-To-Many Self-Reference Associations

The following example demonstrates how to create an one-to-many self-reference association for the Employee class. Sample FluentMetadataSource implementation could be found at the end of the topic.

When you define mapping for a collection property, the HasAssociation property expects the type of the property to be IList<T>. Note that in this example, the Minions property in the Employee class is of type IList<Employee>.

employeeConfiguration.
   HasAssociation( e => e.ReportsTo ).
   WithOpposite( e => e.Minions )
   .HasConstraint( ( e, r ) => e.ReportsToId == r.EmployeeId );
employeeConfiguration.
    HasAssociation(Function(e) e.ReportsTo).
    WithOpposite(Function(e) e.Minions).
    HasConstraint(Function(e, r) e.ReportsToId = r.EmployeeId)

Product Class

public class Product
{
   public int Id {get;set;}
   public string Name {get;set;}
   public bool Discontinued {get;set;}
   public Category Category {get;set;}
   public int CategoryId {get;set;}
}
Public Class Product
    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 _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 _discontinued As Boolean
    Public Property Discontinued() As Boolean
        Get
            Return _discontinued
        End Get
        Set(ByVal value As Boolean)
            _discontinued = value
        End Set
    End Property

    Private _category As Category
    Public Property Category() As Category
        Get
            Return _category
        End Get
        Set(ByVal value As Category)
            _category = value
        End Set
    End Property

    Private _categoryId As Integer
    Public Property CategoryId() As Integer
        Get
            Return _categoryId
        End Get
        Set(ByVal value As Integer)
            _categoryId = value
        End Set
    End Property
End Class

Category Class

public class Category
{
   public Category()
   {
       this.Products = new List<Product>();
   }
   public int Id {get;set;}
   public string Name {get;set;}
   public IList<Product> Products {get;set;}
}
Public Class Category
    Public Sub New()
        Me.Products = New List(Of Product)()
    End Sub
    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 _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 _products As IList(Of Product)
    Public Property Products() As IList(Of Product)
        Get
            Return _products
        End Get
        Set(ByVal value As IList(Of Product))
            _products = value
        End Set
    End Property
End Class

Employee Class

public class Employee
{
   public Employee()
   {
       this.Minions = new List<Employee>();
   }

   public int EmployeeId {get;set;}
   public int ReportsToId {get;set;}
   public Employee ReportsTo {get;set;}
   public IList<Employee> Minions {get;set;}
}
Public Class Employee
    Public Sub New()
        Me.Minions = New System.Collections.Generic.List(Of Employee)()
    End Sub

    Private _employeeId As Integer
    Public Property EmployeeId() As Integer
        Get
            Return _employeeId
        End Get
        Set(ByVal value As Integer)
            _employeeId = value
        End Set
    End Property

    Private _reportsToId As Integer
    Public Property ReportsToId() As Integer
        Get
            Return _reportsToId
        End Get
        Set(ByVal value As Integer)
            _reportsToId = value
        End Set
    End Property

    Private _reportsTo As Employee
    Public Property ReportsTo() As Employee
        Get
            Return _reportsTo
        End Get
        Set(ByVal value As Employee)
            _reportsTo = value
        End Set
    End Property

    Private _minions As System.Collections.Generic.IList(Of Employee)
    Public Property Minions() As System.Collections.Generic.IList(Of Employee)
        Get
            Return _minions
        End Get
        Set(ByVal value As System.Collections.Generic.IList(Of Employee))
            _minions = value
        End Set
    End Property
End Class

Sample FluentMetadataSource Implementation - One-to-Many Association

public class FluentModelMetadataSource : FluentMetadataSource
{
   protected override IList<MappingConfiguration> PrepareMapping()
   {
       List<MappingConfiguration> configurations = new List<MappingConfiguration>();

       MappingConfiguration<Product> productConfiguration = new MappingConfiguration<Product>();
       productConfiguration.MapType( p => new
       {
           ProductId = p.Id,
           ProductName = p.Name,
           Discontinued = p.Discontinued,
           CategoryId = p.CategoryId
       } ).ToTable( "Products" );
       productConfiguration.HasProperty( p => p.Id ).IsIdentity();

       MappingConfiguration<Category> categoryConfiguration = new MappingConfiguration<Category>();
       categoryConfiguration.MapType( p => new
       {
           CategoryId = p.Id,
           CategoryName = p.Name,
       } ).ToTable( "Categories" );
       categoryConfiguration.HasProperty( p => p.Id ).IsIdentity();

       productConfiguration.
           HasAssociation( p => p.Category ).
           WithOpposite( c => c.Products ).
           HasConstraint( ( p, c ) => p.CategoryId == c.Id );

       configurations.Add( productConfiguration );
       configurations.Add( categoryConfiguration );

       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 productConfiguration As New MappingConfiguration(Of Product)()
        productConfiguration.MapType(Function(p) New With { _
            Key .ProductId = p.Id, 
            Key .ProductName = p.Name, 
            Key .Discontinued = p.Discontinued, 
            Key .CategoryId = p.CategoryId}).ToTable("Products")
        productConfiguration.HasProperty(Function(p) p.Id).IsIdentity()
        productConfiguration.FieldNamingRules.AddPrefix = "_"

        Dim categoryConfiguration As New MappingConfiguration(Of Category)()
        categoryConfiguration.MapType(Function(p) New With { _
            Key .CategoryId = p.Id, 
            Key .CategoryName = p.Name}).ToTable("Categories")
        categoryConfiguration.HasProperty(Function(p) p.Id).IsIdentity()
        categoryConfiguration.FieldNamingRules.AddPrefix = "_"

        productConfiguration.
            HasAssociation(Function(p) p.Category).
            WithOpposite(Function(c) c.Products).
            HasConstraint(Function(p, c) p.CategoryId = c.Id)

        configurations.Add(productConfiguration)
        configurations.Add(categoryConfiguration)

        Return configurations
    End Function
End Class

Sample FluentMetadataSource Implementation - One-To-Many Self-Reference Association

public class FluentModelMetadataSource : FluentMetadataSource
{
   protected override IList<MappingConfiguration> PrepareMapping()
   {
       List<MappingConfiguration> configurations = new List<MappingConfiguration>();

       MappingConfiguration<Employee> employeeConfiguration = new MappingConfiguration<Employee>();
       employeeConfiguration.MapType( e => new
       {
           Id = e.EmployeeId,
           ReportsTo = e.ReportsToId
       } );

       employeeConfiguration.HasProperty( p => p.EmployeeId ).IsIdentity( KeyGenerator.Autoinc );

       employeeConfiguration.
           HasAssociation( e => e.ReportsTo ).
           WithOpposite( e => e.Minions )
           .HasConstraint( ( e, r ) => e.ReportsToId == r.EmployeeId );

       configurations.Add( employeeConfiguration );

       return configurations;
   }
}
Public Class FluentModelMetadataSource
    Inherits FluentMetadataSource
    Protected Overrides Function PrepareMapping() As IList(Of MappingConfiguration)
        Dim configurations As New List(Of MappingConfiguration)()

        Dim employeeConfiguration As New MappingConfiguration(Of Employee)()
        employeeConfiguration.MapType(Function(e) New With {
            Key .Id = e.EmployeeId, 
            Key .ReportsTo = e.ReportsToId})
        employeeConfiguration.HasProperty(Function(p) p.EmployeeId). _
            IsIdentity(KeyGenerator.Autoinc)
        employeeConfiguration.FieldNamingRules.AddPrefix = "_"

        employeeConfiguration.
            HasAssociation(Function(e) e.ReportsTo).
            WithOpposite(Function(e) e.Minions).
            HasConstraint(Function(e, r) e.ReportsToId = r.EmployeeId)

        configurations.Add(employeeConfiguration)

        Return configurations
    End Function
End Class