摘要:ADO.NET 中的數據集是一種在內存中表示數據的方法,它可以包含多個相關的數據表。本文介紹了在數據集中瀏覽這些相關數據表的方法。您將在 Visual Basic® .NET 或 Visual C#™ .NET 中創建一個 Windows® 應用程序,基於選定的記錄返回相關記錄,並使用表達式列爲相關記錄生成合計信息。本文包含一些指向英文站點的鏈接。
簡介
由於數據集可以包含幾個相關的表,因此瞭解如何在父記錄和子記錄之間進行瀏覽是一項基本任務,而這並非顯而易見,特別是當您試圖訪問相關層次結構中的深層表中的數據時,更是如此。您還將學習如何瀏覽包含具有多對多關係的表的數據集,其中每個表都通過第三方表(中間表)彼此相關聯。
以下是本文所包含任務的概述:
創建 Windows 應用程序項目。
顯示用作初始選定內容的數據列表。
返回與選定記錄相關的記錄。
瀏覽多個表和多個相關結構,並在運行時直接訪問數據集中的數據。
此外,本文還介紹一些相關的任務:
爲數據表添加基於相關數據的表達式列。
生成相關數據的合計信息。
前提條件
要充分理解本文,您應該具有:
基本的關係數據庫概念的知識。
與羅斯文示例數據庫的有效連接,以便您能夠創建和運行應用程序。
大體上熟悉 ADO.NET 數據集。
重要的數據對象
要使用數據集中的相關記錄,您應基本瞭解 .NET 框架 System.Data 命名空間中的幾個對象以及它們如何相互作用。這些對象協同工作以提供數據集中的導航功能。
以下對象用於表達數據集中的關係:
DataSet - 在內存中表示數據,可以包含多個可與 DataRelation 對象相關的 DataTable 對象。
DataTable - 表示一個完整的數據表。數據表的架構是由構成該表的 DataColumnCollection 定義的。當兩個數據表相關時,DataRelation 對象使用每個表中的 DataColumn 來關聯數據。
DataRelation - 連接多個表,以便瀏覽相關表中的記錄。訪問相關記錄時,DataRelation 對象被傳遞給 GetChildRows 或 GetParentRow 方法。DataRelation 對象確定所要查詢的相關表,以便返回與 GetChildRows 或 GetParentRow 方法調用相關聯的相關數據。
DataRow - 表示數據的一個單獨的記錄。用於返回相關數據的 GetChildRows 方法和 GetParentRow 方法是 DataRow 對象的成員。
DataColumn - 表示一個單獨的字段,結合在一起時將定義 DataTable 的架構。當兩個數據表相關時,DataRelation 對象使用每個表中的數據列來關聯數據。
創建應用程序
本節將建立這一演練的起點。隨後的步驟將創建數據連接、數據適配器和包含相關表的數據集,以及幾個選擇和顯示數據的控件。
創建新的 Windows 應用程序
從 File(文件)菜單中,指向 New(新建),並選擇 Project(項目)。將顯示 New Project(新建項目)對話框。
在 Project Types(項目類型)窗格中,根據您需要的編程語言,選擇 Visual Basic Projects(Visual Basic 項目)或 Visual C# Projects(Visual C# 項目)。
在 Templates(模板)窗格中,選擇 Windows Application(Windows 應用程序),並將其命名爲 DataRelationExample,然後單擊 OK(確定)。
DataRelationExample 項目將添加到 Solution Explorer(解決方案資源管理器)中。
連接到數據庫
此連接允許您與 Visual Studio® 集成開發環境 (IDE) 中的數據源進行通訊。
連接到 Server Explorer(服務器資源管理器)中的羅斯文示例數據庫
在 Server Explorer(服務器資源管理器)中,建立連接到羅斯文示例數據庫的數據連接。
在 Server Explorer(服務器資源管理器)中展開羅斯文數據連接,直到可以看到所有的表。
創建數據適配器和連接
此步驟創建用於在應用程序和數據源之間連接和交換數據的連接和數據適配器。
創建數據適配器和連接
將“客戶”表從 Server Explorer(服務器資源管理器)中拖到窗體上。組件欄中將顯示連接和數據適配器。
選擇 Connection(連接)並將 Name 屬性設置爲 dcNorthwind。
選擇數據適配器並將 Name 屬性設置爲 daCustomers。
將“訂單”表從 Server Explorer(服務器資源管理器)中拖到窗體上。組件欄中將顯示第二個數據適配器。
選擇新的數據適配器並將 Name 屬性設置爲 daOrders。
生成數據集
使用剛剛添加到窗體上的數據適配器生成包含客戶表和訂單表的數據集。
生成將包含相關數據表的數據集
從 Data(數據)菜單中,選擇 Generate Dataset(生成數據集)。將顯示 Generate Dataset(生成數據集)對話框。
提示:將光標移到窗體上即可使用 Data(數據)菜單。
單擊 New(新建)並將數據集命名爲 dsNorthwind。
選擇客戶表和訂單表。
選擇 Add this dataset to the designer(將此數據集添加到設計器)複選框,然後單擊 OK(確定)。
Solution Explorer(解決方案資源管理器)的項目中將添加一個名爲 dsNorthwind.xsd 的文件,並且組件欄中將顯示該數據集的一個實例。
創建關係
生成數據集並不能自動創建數據集中各表之間的關係。關係可以通過編程創建,也可以使用 XML Designer(XML 設計器)直觀地創建。本文使用 XML Designer(XML 設計器)。
創建客戶表和訂單表之間的關係
在 Solution Explorer(解決方案資源管理器)中,雙擊 dsNorthwind.xsd 文件。文件將在 XML Designer(XML 設計器)中打開。
從工具欄的 XML Schema(XML 架構)選項卡中,將 Relation(關係)拖到訂單表上。
在 Edit Relation(編輯關係)對話框中,設置以下屬性:
元素 設置
Name CustomersOrders
Parent Customers
Child Orders
Key Fields CustomerID
Foreign Key Fields CustomerID
單擊 OK(確定)以創建關係並關閉對話框。
從 File(文件)菜單中,選擇 Save All(全部保存)以保存該項目。
顯示數據
此應用程序使用組合框、列表框和 RTF 文本框來選擇和顯示數據。
添加選擇和顯示數據的控件
在 Solution Explorer(解決方案資源管理器)中,右鍵單擊 Form1(.cs 或 .vb,取決於應用程序的語言),然後從快捷菜單中選擇 View Designer(視圖設計器)。
在窗體的左半部,添加一個 ListBox 控件,並將其 Name 屬性設置爲 lbOrders。
在窗體的右半部,添加一個 RichTextBox 控件,並將其 Name 屬性設置爲 rtbDetails。
在列表框的上方,添加一個 ComboBox 控件,並將其 Name 屬性設置爲 cbCustomers。
保存項目。
圖 1:建議的窗體控件佈局
現在,可以開始嚮應用程序添加功能了。
設置顯示公司名稱的組合框
選擇組合框 (cbCustomers) 並設置以下屬性: 屬性 設置
DataSource DsNorthwind1
DisplayMember Customers.CompanyName
ValueMember Customers.CustomerID
用數據填充表
要用數據填充表,必須爲應用程序添加代碼。
在數據集 (dsNorthwind1) 中的客戶表和訂單表中填充數據
雙擊窗體上的一塊空白區域,爲 Form1_Load 事件創建事件處理程序。
添加以下代碼:
' Visual Basic
Private Sub Form1_Load(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Load
' 關閉數據集中的約束。
DsNorthwind1.EnforceConstraints = False
' 用數據填充表。
daOrders.Fill(DsNorthwind1)
daCustomers.Fill(DsNorthwind1)
' 重新開啓約束。
DsNorthwind1.EnforceConstraints = True
End Sub
// C#
private void Form1_Load(object sender, System.EventArgs e)
{
// 關閉數據集中的約束。
dsNorthwind1.EnforceConstraints = false;
// 用數據填充表。
daOrders.Fill(dsNorthwind1);
daCustomers.Fill(dsNorthwind1);
// 重新開啓約束。
dsNorthwind1.EnforceConstraints = true;
}
保存項目。
按 F5 鍵運行該應用程序。現在組合框中包含一個公司名稱列表。
關閉窗體。
在兩個表中瀏覽相關記錄
這裏簡要介紹一下如何在數據集中構成一對多關係的兩個表之間訪問數據。在選擇一個數據行之後,可以通過調用 GetChildRows 或 GetParentRow 方法並向該數據行傳遞適當的數據關係來返回其相關記錄。
注意:GetChildRows 方法將以 DataRow 對象數組的形式返回數據,而 GetParentRow 方法只返回一個單個的數據行。
要演示這一功能,需要給應用程序添加一些代碼,以返回組合框中選定客戶的所有訂單(子行)。更改組合框中的選定客戶會引發 ComboBox.SelectedIndexChanged 事件,列表框中將填充該選定客戶的每個訂單的訂單 ID。
您可以根據組合框中選定的客戶,調用 GetChildRows 方法。訂單表中的所有相關記錄都將分配給名爲 draOrders 的數據行數組。
注意:下一節將添加在列表框中顯示相關訂單列表的功能。爲確認數組中確實包含相關的記錄,數組的長度(即選定客戶的訂單總數)將顯示爲窗體的標題。
創建獲取選定客戶的訂單的事件處理程序
在 Solution Explorer(解決方案資源管理器)中,右鍵單擊 Form1 並從快捷菜單中選擇 View Designer(視圖設計器)。
雙擊組合框爲 SelectedIndexChanged 事件創建事件處理程序。
添加以下代碼:
' Visual Basic
Private Sub cbCustomers_SelectedIndexChanged _
(ByVal sender As System.Object, ByVal e As System.EventArgs) _
Handles cbCustomers.SelectedIndexChanged
' 聲明一個用來保存選定客戶的客戶 ID 的字符串。
Dim SelectedCustomerID As String
SelectedCustomerID = cbCustomers.SelectedValue.ToString()
' 聲明一個用來保存選定客戶的記錄的數據行。
Dim drSelectedCustomer As DataRow
drSelectedCustomer = _
DsNorthwind1.Customers.FindByCustomerID _
(SelectedCustomerID)
' 聲明一個用來保存相關記錄的數據行數組。
Dim draOrders As DataRow()
draOrders = drSelectedCustomer.GetChildRows("CustomersOrders")
' 在窗體標題中顯示數組的長度(訂單數)
' 和客戶 ID。
Me.Text = draOrders.Length.ToString() & " 訂單所有者 " & _
SelectedCustomerID
End Sub
// C#
private void cbCustomers_SelectedIndexChanged
(object sender, System.EventArgs e)
{
// 聲明一個用來保存選定客戶的客戶 ID 的字符串。
String SelectedCustomerID;
SelectedCustomerID = cbCustomers.SelectedValue.ToString();
// 聲明一個用來保存選定客戶的記錄的數據行。
DataRow drSelectedCustomer;
drSelectedCustomer =
dsNorthwind1.Customers.FindByCustomerID(SelectedCustomerID);
// 聲明一個用來保存相關記錄的數據行數組。
DataRow[] draOrders;
draOrders = drSelectedCustomer.GetChildRows("CustomersOrders");
// 在窗體標題中顯示數組的長度(訂單數)
// 和客戶 ID。
this.Text = draOrders.Length.ToString() +
" 訂單所有者 " + SelectedCustomerID;
}
保存項目。
運行應用程序。
選擇另一個客戶,並檢查窗體標題。將顯示選定客戶的訂單總數及其客戶 ID。
關閉窗體。
顯示相關記錄
現在您已經有了選定客戶的相關記錄(存儲在數據行數組中),您可以顯示它們以便與用戶進行交互。應用程序將逐一訪問 GetChildRows 方法返回的數據行數組中的數據,並將每個相關記錄的“訂單 ID”作爲單獨的項添加到列表框中。
注意:雖然此示例將逐一訪問相關數據行數組中的數據,但列表框可能已經使用屬性窗口,通過 DataSource 屬性、DataMember 屬性和 ValueMember 屬性被綁定到相關的記錄。
在列表框中顯示相關記錄
在 Solution Explorer(解決方案資源管理器)中,右鍵單擊 Form1 並從快捷菜單中選擇 View Code(查看代碼)。
在前面步驟中創建的組合框的 SelectedIndexChanged 事件處理程序中,將以下代碼添加到處理程序中已有代碼之下:
' Visual Basic
' 當更改選定客戶時,清除訂單列表。
lbOrders.Items.Clear()
rtbDetails.Text = ""
' 將每個相關訂單的訂單 ID 添加到列表框中。
Dim drOrder As DataRow
For Each drOrder In draOrders
lbOrders.Items.Add(drOrder("OrderID"))
Next
// C#
// 當更改選定客戶時,清除訂單列表。
lbOrders.Items.Clear();
rtbDetails.Text = "";
// 將每個相關訂單的訂單 ID 添加到列表框中。
foreach(DataRow drOrder in draOrders)
{
lbOrders.Items.Add(drOrder["OrderID"]);
}
保存項目。
運行應用程序。
列表框中將顯示訂單列表。在組合框中選擇另一個客戶,訂單列表將被更新。
關閉窗體。
在三個或更多表中瀏覽相關記錄
瀏覽三個或更多表與處理兩個表一樣簡單。要了解如何處理兩個以上的表,請將訂單明細表和產品表添加到 dsNorthwind 數據集中。在列表框中選定一個訂單後,該訂單的詳細信息即顯示在 RTF 文本框中。
爲了滿足約束規則,您需要刪除現有的數據關係,將來再重新創建。
暫時刪除 dsNorthwind 數據集中的 DataRelation
在 Solution Explorer(解決方案資源管理器)中,雙擊 dsNorthwind.xsd 以在 XML Designer(XML 設計器)中打開它。
選擇現有的 CustomersOrders 關係並將其刪除。
保存項目。
現在您需要將另外兩個表添加到現有數據集中,並創建新的 DataRelation 對象以將所有表連在一起。
將訂單明細表和產品表添加到 dsNorthwind 數據集中
在 Solution Explorer(解決方案資源管理器)中,右鍵單擊 Form1 並從快捷菜單中選擇 View Designer(視圖設計器)。
將“訂單明細”表從 Server Explorer(服務器資源管理器)中拖到窗體上。組件欄中將顯示一個新的數據適配器。
選擇該新的數據適配器並將其 Name 屬性設置爲 daOrderDetails。
將“產品”表從 Server Explorer(服務器資源管理器)中拖到窗體上。組件欄中將顯示一個新的數據適配器。
選擇該新的數據適配器並將其 Name 屬性設置爲 daProducts。
新表只是被添加到了窗體上,因此每次添加額外的表時,都必須重新生成數據集。
重新生成 dsNorthwind 數據集
從 Data(數據)菜單中,選擇 Generate Dataset(生成數據集)。
提示:將光標移到窗體上即可使用 Data(數據)菜單。
單擊 Existing(現有),然後選擇 dsNorthwind 數據集。
選擇所有四個表(客戶表、訂單表、訂單明細表和產品表)。
清除 Add this dataset to the designer(將此數據集添加到設計器)複選框,然後單擊 OK(確定)。將生成帶有附加表的數據集。
注意:如果出現一個對話框,其中說明“The file has been modified outside of the source editor. Do you want to reload it?”(文件已在源編輯器之外被修改。是否要重新加載?),請單擊 Yes(是)。
請記住,生成數據集並不能自動創建數據集中各表之間的關係。
創建關係
在 Solution Explorer(解決方案資源管理器)中,雙擊 dsNorthwind.xsd 文件。文件將在 XML Designer(XML 設計器)中打開。
從工具欄的 XML Schema(XML 架構)選項卡中,將 Relation(關係)拖到訂單表上。
在 Edit Relation(編輯關係)對話框中,設置以下屬性:
元素 設置
Name CustomersOrders
Parent Customers
Child Orders
Key Fields CustomerID
Foreign Key Fields CustomerID
單擊 OK(確定)以創建關係並關閉對話框。
從工具欄的 XML Schema(XML 架構)選項卡中,將 Relation(關係)拖到訂單明細表上。
在 Edit Relation(編輯關係)對話框中,設置以下屬性:
元素 設置
Name OrdersOrderDetails
Parent Orders
Child OrderDetails
Key Fields OrderID
Foreign Key Fields OrderID
單擊 OK(確定)以創建關係並關閉對話框。
從工具欄的 XML Schema(XML 架構)選項卡中,將 Relation(關係)拖到訂單明細表上。
在 Edit Relation(編輯關係)對話框中,設置以下屬性:
元素 設置
Name ProductsOrderDetails
Parent Products
Child OrderDetails
Key Fields ProductID
Foreign Key Fields ProductID
單擊 OK(確定)以創建關係並關閉對話框。
保存項目。
訂單明細表和產品表已被添加到數據集中,但是您仍需要添加代碼,以便在運行時用數據來填充它們。
用數據填充表
在 Solution Explorer(解決方案資源管理器)中,右鍵單擊 Form1 並從快捷菜單中選擇 View Code(查看代碼)。
在 Form1_Load 事件處理程序中,將以下代碼添加到註釋“用數據填充表”與 daOrders.Fill(dsNorthwind1) 行之間:
' Visual Basic
daOrderDetails.Fill(dsNorthwind1)
daProducts.Fill(dsNorthwind1)
// C#
daOrderDetails.Fill(dsNorthwind1);
daProducts.Fill(dsNorthwind1);
用數據填充 RTF 文本框
現在您要爲項目添加代碼,以便在列表框中選定某個訂單時,可以在 RTF 文本框中顯示所有訂單明細。
以下代碼將基於列表框中的選定訂單調用 GetChildRows 方法。訂單明細表中的所有相關記錄都將分配給名爲 draOrderDetails 的數據行數組。每個數據行的內容將顯示在 RTF 文本框中。
注意:請注意嵌套的 For Each 循環是如何首先選取一個數據行,然後在該數據行的所有列中循環以訪問整個相關記錄的。
設置 RTF 文本框以顯示所有訂單明細
在 Solution Explorer(解決方案資源管理器)中,右鍵單擊 Form1 並從快捷菜單中選擇 View Designer(視圖設計器)。
雙擊列表框爲列表框 lbOrders 的 SelectedIndexChanged 事件創建事件處理程序。
添加以下代碼:
' Visual Basic
Private Sub lbOrders_SelectedIndexChanged _
(ByVal sender As System.Object, ByVal e As System.EventArgs) _
Handles lbOrders.SelectedIndexChanged
' 選擇新訂單時,清除 RTF 文本框。
rtbDetails.Clear()
' 聲明一個用來保存選定的訂單 ID 的整數。
Dim SelectedOrderID As Integer
' 將選定的項目設置爲整數。
SelectedOrderID = CType(lbOrders.SelectedItem, Integer)
' 聲明一個用來保存選定訂單的記錄的數據行。
Dim drSelectedOrder As DataRow
drSelectedOrder = _
DsNorthwind1.Orders.FindByOrderID(SelectedOrderID)
' 聲明一個用來保存相關記錄的數據行數組。
Dim draOrderDetails() As DataRow
draOrderDetails = _
drSelectedOrder.GetChildRows("OrdersOrderDetails")
Dim details As String = ""
Dim drDetails As DataRow
Dim dcDetails As DataColumn
For Each drDetails In draOrderDetails
For Each dcDetails In drDetails.Table.Columns
details &= dcDetails.ColumnName & ": "
details &= drDetails(dcDetails).ToString()
details &= ControlChars.CrLf
Next
details &= ControlChars.CrLf
Next
rtbDetails.Text = details
End Sub
// C#
private void lbOrders_SelectedIndexChanged
(object sender, System.EventArgs e)
{
// 選擇新訂單時,清除 RTF 文本框。
rtbDetails.Clear();
// 聲明一個用來保存選定的訂單 ID 的整數。
int SelectedOrderID;
// 將選定的項目設置爲整數。
SelectedOrderID = (int)lbOrders.SelectedItem;
// 聲明一個用來保存選定訂單的記錄的數據行。
DataRow drSelectedOrder;
drSelectedOrder =
dsNorthwind1.Orders.FindByOrderID(SelectedOrderID);
// 聲明一個用來保存相關記錄的數據行數組。
DataRow[] draOrderDetails;
draOrderDetails =
drSelectedOrder.GetChildRows("OrdersOrderDetails");
string details = "";
foreach(DataRow drDetails in draOrderDetails)
{
foreach(DataColumn dcDetails in drDetails.Table.Columns)
{
details += dcDetails.ColumnName + ": ";
details += drDetails[dcDetails].ToString() + "/n";
}
details += "/n";
}
rtbDetails.Text = details;
}
保存項目。
運行應用程序。
在列表框中選擇一個訂單,其訂單明細將顯示在 RTF 文本框中。
在列表框中選擇另一個訂單。RTF 文本框中的訂單明細將被更新。
瀏覽多對多關係
構成多對多關係的表通常通過保證數據完整性的第三方表進行連接。在羅斯文數據庫中,訂單表和產品表就是這樣相關的。因爲有些訂單可能包含很多產品,而有些產品又在很多訂單中銷售。這兩個表是通過訂單明細表連接的,訂單明細表利用這兩個表中的列建立自己特定的列,並使這些數據相關。瀏覽構成多對多關係的三個表與處理一對多關係的表並沒有太大區別。
要瀏覽多對多關係,您可以基於訂單明細表中的單個記錄來訪問產品,這將返回產品名稱並顯示在訂單明細中。
您可以使用 GetParentRow 方法從產品表中訪問產品名稱。調用 GetParentRow 方法將返回單個數據行,而調用 GetChildRows 方法將返回數據行數組(如上例所示)。
從訂單明細記錄中獲取產品名稱
在 Solution Explorer(解決方案資源管理器)中,右鍵單擊 Form1 並從快捷菜單中選擇 View Code(查看代碼)。
在列表框 (lbOrders) 的 SelectedIndexChanged 事件處理程序中,將以下代碼添加到 For Each 行之間:
' Visual Basic
details &= "產品名稱: " & _
CType(drDetails.GetParentRow("ProductsOrderDetails") _
("ProductName"), String) & ControlChars.CrLf
// C#
details += "產品名稱: " +
drDetails.GetParentRow("ProductsOrderDetails")["ProductName"]
+ "/n";
保存項目。
運行應用程序。
在列表框中選擇一個訂單,
RTF 文本框中將顯示產品名稱和詳細信息。現在窗體中顯示來自所有四個表的相關數據。
圖 2:顯示產品名稱和訂單明細的窗體
在列表框中選擇另一個訂單。RTF 文本框中的訂單明細將被更新。
關閉窗體。 表達式列
除了包含靜態數據外,還可以基於表達式的結果爲 DataColumn 分配值。表達式是一個分配給 DataColumn.Expression 屬性的字符串。
當表達式與相關數據一同使用時,數據列可以包含:
相關數據列的計算所得值。
相關數據列的合計信息。
相關數據的邏輯比較結果。
爲說明處理相關數據時的值表達式列,我們將針對每種使用情況介紹一個示例,並添加到 DataRelationExample 應用程序中。
添加包含計算值的表達式列
計算的列包含數學運算結果。可以從現有的列中取值進行計算。訂單明細表中將添加一個名爲 Total 的新列,它將包含由表達式 UnitPrice * Quantity 返回的值(訂單的總計美元值)。
添加表達式列
在 Solution Explorer(解決方案資源管理器)中,右鍵單擊 Form1 並從快捷菜單中選擇 View Code(查看代碼)。
將以下代碼添加到 Form1_Load 事件處理程序中已有代碼之上:
' Visual Basic
' 在訂單明細表中創建名爲 Total 的表達式列。
Dim dcTotal as DataColumn = new DataColumn("Total")
dcTotal.DataType = System.Type.GetType("System.Decimal")
dcTotal.Expression = "UnitPrice * Quantity"
DsNorthwind1.Order_Details.Columns.Add(dcTotal)
// C#
// 在訂單明細表中創建名爲 Total 的表達式列。
DataColumn dcTotal = new DataColumn("Total");
dcTotal.DataType = System.Type.GetType("System.Decimal");
dcTotal.Expression = "UnitPrice * Quantity";
dsNorthwind1.Order_Details.Columns.Add(dcTotal);
運行應用程序。
在列表框中選擇一個訂單,
檢查 RTF 文本框中的訂單明細,並注意每個記錄都有一個新的 Total 列,顯示 UnitPrice 和 Quantity 字段的乘積。
關閉窗體。
添加包含合計信息的表達式列
Expression 屬性支持幾個合計功能(Sum、Avg、Count 等)。有關詳細信息,請參閱 DataColumn.Expression 屬性。
爲演示如何生成合計信息,需要在訂單表中添加一個名爲 OrderTotal 的新列。此列將使用 Sum 功能,根據在列表框 (lbOrders) 中選定的訂單返回所有子訂單明細記錄的總計美元值。然後,該值將顯示在 RTF 文本框中每個訂單明細的上方。
創建 OrderTotal 列
在 Solution Explorer(解決方案資源管理器)中,右鍵單擊 Form1 並從快捷菜單中選擇 View Code(查看代碼)。
在 Form1_Load 事件處理程序中,將以下代碼添加到在訂單明細表中創建 Total 列的代碼的下方:
' Visual Basic
' 在訂單表中創建名爲 OrderTotal 的表達式列。
Dim dcOrderTotal as DataColumn = new DataColumn("OrderTotal")
dcOrderTotal.DataType = System.Type.GetType("System.Decimal")
dcOrderTotal.Expression = "Sum(Child.Total)"
DsNorthwind1.Orders.Columns.Add(dcOrderTotal)
// C#
// 在訂單表中創建名爲 OrderTotal 的表達式列。
DataColumn dcTotal2 = new DataColumn("OrderTotal");
dcTotal2.DataType = System.Type.GetType("System.Decimal");
dcTotal2.Expression = "Sum(Child.Total)";
dsNorthwind1.Orders.Columns.Add(dcTotal2);
將合計信息顯示在所有訂單明細的上方
在 lbOrders_SelectedIndexChanged 事件處理程序中,將以下代碼添加到 Dim details As String = "" 或 string details = "" 行之下:
' Visual Basic
details = "訂單總計: " & String.Format("{0:c}", _
DsNorthwind1.Orders.FindByOrderID(CType(lbOrders.SelectedItem, _
Integer))("OrderTotal")) & ControlChars.CrLf
// C#
details = "訂單總計: " +
String.Format("{0:c}",dsNorthwind1.Orders.FindByOrderID
((int)lbOrders.SelectedItem)["OrderTotal"]) + "/n";
運行應用程序。
在列表框中選擇一個訂單,
請注意,選定訂單的所有訂單明細的總計金額將顯示在 RTF 文本框中的第一行。
在列表框中選擇另一個訂單,將更新顯示以反映新選擇的訂單。
關閉窗體。
添加包含邏輯求值的表達式列
Expression 屬性可以基於其他列中的計算值來填充某個數據列。例如,訂單表中的 OrderSize 列可以包含值“Big”(如果訂單總額大於 1000)或者“Small”(如果訂單總額小於 1000)。
爲演示這類表達式,需要在 DataRelationExample 應用程序中添加代碼以執行以下操作:
在訂單表中添加名爲 OrderSize 的數據列。
根據相關訂單明細的值來填充 OrderSize 列。
在 RTF 文本框的頂部同時顯示 OrderSize 列的值和 OrderTotal 的值。
添加創建 OrderSize 列的代碼
在 Solution Explorer(解決方案資源管理器)中,右鍵單擊 Form1 並從快捷菜單中選擇 View Code(查看代碼)。
在 Form1_Load 事件處理程序中,將以下代碼添加到在訂單表中創建 OrderTotal 列的代碼的下方:
' Visual Basic
' 在訂單表中創建名爲 OrderSize 的表達式列。
Dim dcOrderSize as DataColumn = new DataColumn("OrderSize")
dcOrderSize.DataType = System.Type.GetType("System.String")
dcOrderSize.Expression = "IIF(Sum(Child.Total)<1000,'Small','Big')"
DsNorthwind1.Orders.Columns.Add(dcOrderSize)
// C#
// 在訂單表中創建名爲 OrderSize 的表達式列。
DataColumn dcOrderSize = new DataColumn("OrderSize");
dcOrderSize.DataType = System.Type.GetType("System.String");
dcOrderSize.Expression = "IIF(Sum(Child.Total)<1000,'Small','Big')";
dsNorthwind1.Orders.Columns.Add(dcOrderSize);
顯示 OrderSize 的值
在 lbOrders_SelectedIndexChanged 事件處理程序中,將以下代碼添加到第一個 For Each 行的上方:
' Visual Basic
details &= " (" & CType(DsNorthwind1.Orders.FindByOrderID _
(CType(lbOrders.SelectedItem, Integer))("OrderSize"), String) & ")" _
& ControlChars.CrLf
// C#
details += " (" + dsNorthwind1.Orders.FindByOrderID
((int)lbOrders.SelectedItem)["OrderSize"] + ")/n";
運行應用程序。
在列表框中選擇一個訂單。
檢查 RTF 文本框中的第一行。選定訂單的 OrderSize 將顯示在 OrderTotal 的右側。
在列表框中選擇另一個訂單,將更新顯示以反映新選擇的訂單。
從 Debug(調試)菜單中,選擇 Stop Debugging(停止調試)。
有關相關表的其他信息
這裏有必要提及一些其他信息以豐富本文的內容。
填充相關數據表的順序非常重要
相關數據表的填充順序對數據的輸出有很大影響,因此必須在設計應用程序時予以考慮。例如,請注意最後一個填充的客戶表的情況。當填充客戶表時,組合框將填充客戶名稱值。填充組合框時,會引發 SelectedIndexChanged 事件。這將執行事件處理程序中的代碼。由於尚未填充訂單表,GetChildRows 方法將返回零 (0) 個記錄,窗體的標題將顯示錯誤信息。試一試:更改代碼以首先填充客戶表,並運行應用程序。窗體的標題顯示 ALFKI 的零 (0) 個訂單,這是不正確的。
返回相關記錄的特定版本
通過將所需的 DataRowVersion 作爲第二個(可選的)參數傳遞給 GetChildRows 或 GetParentRow 方法,可以返回數據行的特定版本。以該應用程序爲例,如果只想查看特定客戶的原始訂單,可以將組合框的 SelectedIndexChanged 事件中的代碼更改爲類似如下的代碼。由於此應用程序中的數據並未更改,以下代碼不會產生明顯的效果,這裏只是作爲一個說明。
' Visual Basic
' 只用選定客戶的原始子行
' 填充數組。
Dim draOrders As DataRow() = DsNorthwind1.Customers.FindByCustomerID _
(cbCustomers.SelectedValue.ToString()).GetChildRows _
("CustomersOrders", DataRowVersion.Original)
// C#
// 只用選定客戶的原始子行
// 填充數組。
DataRow draOrders = dsNorthwind1.Customers.FindByCustomerID
(cbCustomers.SelectedValue.ToString()).GetChildRows
("CustomerOrders", DataRowVersion.Original);
總結
要訪問特定數據行的相關記錄,可以調用該行的 GetChildRows 或 GetParentRow 方法,以傳遞連接該數據行及其相關記錄的數據關係。然後,便可以通過檢查由該方法調用返回的數據行(或數據行數組)來訪問相關的記錄。
通過爲 DataColumn.Expression 屬性分配一個有效的表達式字符串並將數據列添加到相應的 DataTable.Columns 集合中,可以對相關記錄中的值進行計算,合計和邏輯求值。