System.Data.DataRelation类型是一个包含表对表关系的OO包装器。创建新的DataRelation类型时必须指定一个名称,然后是父表(例如,Inventory)和关联的子表(Orders)。要建立关系的话,那么每个表都必须有一个相同数据类型(本例中为Int32)的同名列(CarID)。这样,DataRelation必须根据关系数据库的相同规则来约束。下面是完整的BuildTableRelationship()帮助函数的实现:
private void BuildTableRelationship()
{
// Create a DR obj.
DataRelation dr = new DataRelation("CustomerOrder",
carsDataSet.Tables["Customers"].Columns["CustID"], // Parent.
carsDataSet.Tables["Orders"].Columns["CustID"]); // Child.
// Add to the DataSet.
carsDataSet.Relations.Add(dr);
// Create another DR obj.
dr = new DataRelation("InventoryOrder",
carsDataSet.Tables["Inventory"].Columns["CarID"], // Parent.
carsDataSet.Tables["Orders"].Columns["CarID"]); // Child.
// Add to the DataSet.
carsDataSet.Relations.Add(dr);
}
可以看到,DataSet所维护的DataRelationCollection中保存了一个DataRelation。这个DataRelation类型提供了很多属性,根据这些属性您可以获得对参与该关系中的父/子表的引用、指定关系的名称等(见表A-11)。
表A-11 DataRelation类型的属性
DataRelation属性 | 意 义 |
ChildColumns ChildKeyConstraint ChildTable | 获得这个关系中子表以及这个表的相关信息 |
DataSet | 获得关系集合所属的DataSet |
ParentColumns ParentKeyConstraint ParentTable | 获得这个关系中父表以及这个表的相关信息 |
RelationName | 获得或设置在父表数据集的DataRelationCollection中查找这个关系所用的名称 |
在关联表之间导航
我们可以把GUI扩展为包含一个新的按钮类型和相关的文本框,这样可以说明DataRelation如何允许在关联表进行移动。终端用户可以输入客户的ID并获得这个客户的所有订单信息,这些信息都放在一个简单的消息框中(见图A-20)。
图A-20 导航数据关系
下面显示了按钮的单击事件处理程序(为了简洁起见,已经删除了错误检查部分):
protected void btnGetInfo_Click (object sender, System.EventArgs e)
{
string strInfo = "";
DataRow drCust = null;
DataRow[] drsOrder = null;
// Get the specified CustID from the TextBox.
int theCust = int.Parse(this.txtCustID.Text);
// Now based on CustID, get the correct row in Customers table.
drCust = carsDataSet.Tables["Customers"].Rows[theCust];
strInfo += "Cust #" + drCust["CustID"].ToString() + "/n";
// Navigate from customer table to order table.
drsOrder = drCust.GetChildRows(carsDataSet.Relations["CustomerOrder"]);
// Get customer name.
foreach(DataRow r in drsOrder)
strInfo += "Order Number: " + r["OrderID"] + "/n";
// Now navigate from order table to inventory table.
DataRow[] drsInv =
drsOrder[0].GetParentRows(carsDataSet.Relations["InventoryOrder"]);
// Get Car info.
foreach(DataRow r in drsInv)
{
strInfo += "Make: " + r["Make"] + "/n";
strInfo += "Color: " + r["Color"] + "/n";
strInfo += "Pet Name: " + r["PetName"] + "/n";
}
MessageBox.Show(strInfo, "Info based on cust ID");
}
可以看到,在数据表之间移动最关键就是使用一些DataRow类型定义的方法。让我们一步步地看这段代码。首先从文本框中获得正确的客户ID,然后用它来找到Customer表中正确的行(当然是使用Rows属性),如下所示:
// Get the specified CustID from the TextBox.
int theCust = int.Parse(this.txtCustID.Text);
// Now based on CustID, get the correct row in Customers table.
DataRow drCust = null;
drCust = carsDataSet.Tables["Customers"].Rows[theCust];
strInfo += "Cust #" + drCust["CustID"].ToString() + "/n";
接下来通过CustomerOrder数据关系从Customers表导航到Orders表。注意,DataRow.GetChildRows()方法可以获得子表中的行,这样就可以读取表中信息,如下所示:
// Navigate from customer table to order table.
DataRow[] drsOrder = null;
drsOrder = drCust.GetChildRows(carsDataSet.Relations["CustomerOrder"]);
// Get customer name.
foreach(DataRow r in drsOrder)
strInfo += "Order Number: " + r["OrderID"] + "/n";
最后一步就是使用GetParentRows()方法从Orders表导航到父表(Inventory)。这时您可以用Make、PetName和Color列来读取Inventory表的信息,如下所示:
// Now navigate from order table to inventory table.
DataRow[] drsInv =
drsOrder[0].GetParentRows(carsDataSet.Relations["InventoryOrder"]);
foreach(DataRow r in drsInv)
{
strInfo += "Make: " + r["Make"] + "/n";
strInfo += "Color: " + r["Color"] + "/n";
strInfo += "Pet Name: " + r["PetName"] + "/n";
}
作为以编程方式导航关系的最后一个例子,下面的代码打印出间接通过InventoryOrders关系获得的Orders表中的值:
protected void btnGetChildRels_Click (object sender, System.EventArgs e)
{
// Ask the CarsDataSet for the child relations of the inv. table.
DataRelationCollection relCol;
DataRow[] arrRows;
string info = "";
relCol = carsDataSet.Tables["inventory"].ChildRelations;
info += "/tRelation is called: " + relCol[0].RelationName + "/n/n";
// Now loop over each relation and print out info.
foreach(DataRelation dr in relCol)
{
foreach(DataRow r in inventoryTable.Rows)
{
arrRows = r.GetChildRows(dr);
// Print out the value of each column in the row.
for (int i = 0; i < arrRows.Length; i++)
{
foreach(DataColumn dc in arrRows[i].Table.Columns )
{
info += "/t" + arrRows[i][dc];
}
info += "/n";
}
}
MessageBox.Show(info,
"Data in Orders Table obtained by child relations");
}
}
图A-21显示了输出结果。
图A-21 导航父/子关系
希望最后这个例子能让您彻底了解DataSet类型的用法。由于DataSet完全断开了与底层数据源的连接,您就可以对数据的内存副本进行操作,并在每个表之间导航来进行所需的更新、删除或添加。当完成操作后,您可以把修改提交到数据存储中去处理.