综上所述,整个 SQL 查询可以被分解成 3 条子查询命令—— 1 条核心子查询,用于获取订单记录;2 条辅助子查询,用于建立提交者ID - 提交者名字和客户ID - 客户公司名两个对照表,即:
SELECT employeeid, lastname FROM Employees SELECT customerid, companyname FROM Customers
以下 ADO.NET 代码演示了如何把这 3 条子查询的返回结果集保存到 DataSet 对象中。
Dim conn As SqlConnection = New SqlConnection(connString) Dim adapter As SqlDataAdapter = New SqlDataAdapter()
conn.Open() adapter.SelectCommand = New SqlCommand(cmdCore, conn) adapter.SelectCommand.Parameters.Add("@TheYear", 1997) adapter.SelectCommand.Parameters.Add("@TheQuantity", 30) adapter.Fill(ds, "Orders") adapter.SelectCommand = New SqlCommand(cmdCust, conn) adapter.Fill(ds, "Customers") adapter.SelectCommand = New SqlCommand(cmdEmpl, conn) adapter.Fill(ds, "Employees") conn.Close()
请注意:在连续执行 SQL 查询命令时,你通常都要自行操作数据库连接,以免出现多余的open/close 操作。本例的 adapter.Fill 方法会自动执行 open/close 操作,除非你设置 adapter.SelectCommmand 属性把某个连接显式关联到 adapter 对象之上。
为了建立内存数据表之间的关系链,你可以创建两个关系,把 employeeid (提交者的ID) 关联到 lastname (提交者的名字),把 customerid (客户的ID) 关联到 companyname (客户的公司名)。一般情况下,可以用 DataRelation 对象在同一 DataSet 对象内创建两个独立表之间的一对多关系。然而,本例却需要建立多对一关系,这是很少见的。其实,只要把一对多关系中的父表(Orders) 变成子表,而把子表(Employees、Customers) 变成父表就行了。

图 2. 关系中的父表与子表角色互换
ADO.NET 中的 DataRelation 对象相当灵活,足以构建多对一关系。每生成一个DataRelation 对象,ADO.NET 都会在后台为之建立一致性约束,以免父表内的键值重复。当然了,一旦重复的键值出现,ADO.NET 就会抛出(throw)一个例外。请看下列代码: Dim relOrder2Employees As DataRelation relOrder2Employees = New DataRelation("Orders2Employees", _ ds.Tables("Orders").Columns("employeeid"), _ ds.Tables("Employees").Columns("employeeid")) ds.Relations.Add(relOrder2Employees) 此处的 DataRelation 对象构造器初始化了三个参数:第一个是关系名称,后面两个是 DataColumn 对象,分别代表构成关系的两个列(column):前一个 DataColumn 对象代表父列,后一个 DataColumn 对象代表子列。一旦构造器发现父列中不存在合法记录,便会激活(raise) 一个 ArgumentException 例外。消除此例外最简单的解决方案是在构造器中添加一个布尔值作为第四参数: relOrder2Employees = New DataRelation("Orders2Employees", _ ds.Tables("Orders").Columns("employeeid"), _ ds.Tables("Employees").Columns("employeeid"), _ False)
当构造器的第四参数值为 false 时,ADO.NET 就不会建立一致性约束,而后者正是引发 ArgumentException 例外的罪魁祸首。
设置了数据关系之后,你就可以用列表达式 (computed column) 给 Orders 表添加两列以显示其内容了。理论上,这么做完全符合逻辑:
Dim orders As DataTable = ds.Tables("Orders") orders.Columns.Add("Employee", GetType(String), _ "Child(Orders2Employees).lastname") orders.Columns.Add("Customer", GetType(String), _ "Child(Orders2Customers).companyname")
可惜,它根本行不通。更糟的是,当它运行到包含 Child 的代码时,就会抛出 (throw) 一条 “句法错误”信息,而这条出错信息很容易误导程序员。(有关列表达式的更多信息,请参阅《last month's column》。)
上一页 [1] [2] [3] [4] [5] [6] 下一页
|