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

How to: Handle Relationships

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.

So far in this section, you've worked with single entities without dealing with any of their associations or relationships. In the How to: Load Related Data topic, you learn how to add a query method in the Domain Service to return related data. But in reality, you work with relational data, and that means working with child/parent entities. This topic will give you general guidelines about working with relationships in WCF RIA applications.

How to Handle One-to-Many Relationships

By default, the Domain Service does not generate any code for associations in your domain entity classes. Consider the following entities.

The generated Product proxy class won't have any reference to the Category property. To make that property generated you need to annotate the Product.Category property with the AssociationAttribute and IncludeAttribute.

You should add a new metadata class for the Product entity, as follows:

public partial class Product
   internal sealed class ProductMetadata
       // [Association("The name of the property", 
       //"Product.CategoryId (the foreign key)", 
       //"Category.CategoryID (the other side primary key")]
       [Association("Category", "CategoryID", "CategoryID")]
       public Category Category { get; set; }
Partial Public Class Product
 Friend NotInheritable Class ProductMetadata
  ' [Association("The name of the property", _
  ' "Product.CategoryId (the foreign key)", _
  ' "Category.CategoryID (the other side primary key")]
  <Include, Association("Category", "CategoryID", "CategoryID")>
  Public Property Category() As Category
 End Class
End Class

The AssociationAttribute is used to represent an association in the database, such as the relationship between a foreign key and a primary key. It informs WCF RIA that the Category property can be reconstructed on the client by comparing the Product.CategoryId (the foreign key) to the Category.CategoryId( the other side primary key). When applied to an entity association, the IncludeAttribute indicates that the association should be part of any code generated client entities, and that any related entities should be included when serializing results to the client.

For more information about metadata classes, take a look at How to: Add Metadata Class.

Now you have the association between your domain entity classes included in the generated Product class on the client (Silverlight) side.

Category category = new Category();
category.CategoryName = "My Category";
category.Description = "Some Description";
Product product = new Product();
product.Discontinued = false;
product.ProductName = "My Product";
product.Category = category;
// It is enough just to pass the root object in the hierarchy.
// dbContext.Categories.Add(category); --- not needed.
Dim _category As New Category()
_category.CategoryName = "My Category"
_category.Description = "Some Description"
Dim _product As New Product()
_product.Discontinued = False
_product.ProductName = "My Product"
_product.Category = _category
' It is enough just to pass the root object in the hierarchy.
' dbContext.Categories.Add(category); --- not needed.

How to Handle Many-to-Many Relationships

WCF RIA data services does not support Many-to-Many relationships out of the box. The only possibility for now is to reverse map your join table and use it as a real entity. This way you will be able to do a One-To-Many associations from your two other entities to the join table.

Consider the following many-to-many relationship between the Employee and Territory entities from the Northwind database.

In order to generate persistent type for the join table, you need to perform the following steps:

  • Delete the existing many-to-many relation.
  • Open the Model Schema Explorer and expand the Tables node.
  • Select the join table (in this case it will be EmployeeTerritories). Press F4 to open the Properties pane and set the IsJoinTable property to False.
  • Navigate back to the Model Schema Explorer. Select the join table, right-click to open the context menu and select Map to persistent type.

Finally, your diagram should be similar to the snapshot below:

There are several specific things that should be pointed out here. If you have already created your domain service, then you have to delete it and re-generate it. However in this case, when you generate the new domain service, you have to choose the From Rlinq File option in the Choose Telerik Data Access domain model type dialog.

Once your domain service is generated, you need to create a metadata class for the EmployeeTerritory entity and decorate the Employee and Territory properties with AssociationAttribute and IncludeAttribute.

public partial class EmployeeTerritory
internal sealed class EmployeeTerritoryMetadata
 [Association("Employee", "EmployeeID", "EmployeeID")]
 public Employee Employee { get; set; }
 [Association("Territory", "TerritoryID", "TerritoryID")]
 public Territory Territory { get; set; }
Partial Public Class EmployeeTerritory
 Friend NotInheritable Class EmployeeTerritoryMetadata
  <Include, Association("Employee", "EmployeeID", "EmployeeID")>
  Public Property Employee() As Employee
  <Include, Association("Territory", "TerritoryID", "TerritoryID")>
  Public Property Territory() As Territory
 End Class
End Class

In the client application (in the Silverlight application), you could use the generated proxy association in the following manner:

DomainService1 domainService = new DomainService1();
Employee employee = new Employee();
employee.FirstName = "Petar";
employee.LastName = "Ivanov";
Territory territory = new Territory();
territory.TerritoryID = "MyTerritory2";
territory.TerritoryDescription = "Some description";
territory.RegionID = 1;
EmployeeTerritory empTer = new EmployeeTerritory();
empTer.EmployeeID = employee.EmployeeID;
empTer.Employee = employee;
empTer.TerritoryID = territory.TerritoryID;
empTer.Territory = territory;
Dim domainService As New DomainService1()
Dim _employee As New Employee()
_employee.FirstName = "Petar"
_employee.LastName = "Ivanov"
Dim _territory As New Territory()
_territory.TerritoryID = "MyTerritory2"
_territory.TerritoryDescription = "Some description"
_territory.RegionID = 1
Dim empTer As New EmployeeTerritory()
empTer.EmployeeID = _employee.EmployeeID
empTer.Employee = _employee
empTer.TerritoryID = _territory.TerritoryID
empTer.Territory = _territory