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