DekGenius.com
[ Team LiB ] Previous Section Next Section

11.1 DataRelation Object Overview

Every DataSet contains a DataRelationCollection object, which contains DataRelation objects. Each DataRelation defines a relationship between two tables. There are two reasons why you might define DataRelation objects:

  • To provide better error checking (for example, spotting an orphaned child before you reconnect to update the data source). This functionality is provided through the ForeignKeyConstraint, which the DataRelation can create implicitly.

  • To provide better navigation.

A typical DataRelation requires three pieces of information: a descriptive name of your choosing (which doesn't signify anything or relate to the data source), a reference to the parent DataColumn, and a reference to the child DataColumn. You can add this information with the DataRelation constructor:

DataRelation relation = new DataRelation("Name", ParentCol, ChildCol);

Once you've defined the DataRelation object, you need to add it to the DataSet:

ds.Relations.Add(relation);

For example, to create a relationship between product categories and products, use the following code:

DataColumn parentCol = ds.Tables["Categories"].Columns["CategoryID"];
DataColumn childCol = ds.Tables["Products"].Columns["CategoryID"];
DataRelation relation = new DataRelation("Cat_Prod", parentCol, childCol);

ds.Relations.Add(relation);

If you attempt to create a DataRelation, and the parent record column isn't unique, or there are child records that refer to nonexistent parents, an exception is thrown.

Currently, there is no way to automatically add a DataRelation object based on the relationships defined in the data source. That means that if you want to use relations, either to enforce data integrity or provide parent-child navigation, you need to create them yourself.

11.1.1 DataRelations and Constraints

At first glance, the DataRelation seems to duplicate some of the functionality provided by the ForeignKeyConstraint to enforce referential integrity. However, this isn't really the case. The DataRelation actually uses the Constraint classes. By default, when you create a new DataRelation, a UniqueConstraint is created automatically for the parent column and added to the parent table if it doesn't already exist. At the same time, a ForeignKeyConstraint is created for the child column and added to the child table. Thus, the rules governing relational integrity are exactly the same as those discussed in Chapter 10.

In some cases, you might want to create a DataRelation without generating any constraints. This allows you to use a relation to aid navigation but not enforce it as a data validation rule. One reason why you might not want to enforce a relationship could be because you have queried only a subset of the total parent rows in the data source. Consequently, there may be child rows that reference a valid parent row that isn't a part of the DataSet.

To make sure constraints are generated, you must use the DataRelation constructor that accepts an additional Boolean value. If you supply false, the Constraint objects aren't generated.

DataRelation relation = new DataRelation("Name", ParentCol, 
                                         ChildCol, false);

You can still use the DataRelation for navigation, but referentially integrity will not be enforced on the DataSet.

As explained in Chapter 10, you can configure the ForeignKeyConstraint to specify if deletes and updates are cascaded. When using a DataRelation, you can still use this feature; you simply need to modify the automatically generated ForeignKeyConstraint, which is available through the DataRelation.ChildKeyConstraint property.

    [ Team LiB ] Previous Section Next Section