共用方式為


更新 TableAdapter 以使用 JOIN (C#)

作者:Scott Mitchell

下載 PDF

使用資料庫時,通常會要求分散於多個資料表的資料。 若要從兩個不同的資料表擷取資料,我們可以使用相互關聯的子查詢或 JOIN 作業。 在本教學課程中,我們會先比較相互關聯的子查詢和 JOIN 語法,再探討如何建立 TableAdapter,在其主查詢中包含 JOIN。

簡介

使用關聯式資料庫時,我們感興趣的資料通常分散在多個資料表。 例如,當顯示產品資訊時,我們可能會想要列出每個產品相對應的類別和供應商名稱。 Products 資料表具有 CategoryIDSupplierID 值,但實際的類別和供應商名稱分別位於 CategoriesSuppliers 資料表中。

若要從另一個相關資料表擷取資訊,我們可以使用「相互關聯的子查詢」JOIN。 相互關聯的子查詢是巢狀 SELECT 查詢,會參考外部查詢中的資料行。 例如,在建立資料存取層教學課程中,我們使用了兩個相互關聯的子查詢在 ProductsTableAdapter 的主查詢中傳回每個產品的類別和供應商名稱。 JOIN 是一種 SQL 建構函式,可合併兩個不同資料表的相關資料列。 我們在使用 SqlDataSource 控制項查詢資料教學課程使用了 JOIN,在每個產品一旁顯示類別資訊。

我們避開搭配 TableAdapter 使用 JOIN 的原因是,TableAdapter 精靈中對自動產生相對應的 INSERTUPDATEDELETE 陳述式有所限制。 更具體來說,如果 TableAdapter 的主查詢包含任何 JOIN,TableAdapter 就無法自動為其 InsertCommandUpdateCommandDeleteCommand 屬性建立臨機操作 SQL 陳述式或預存程序。

在本教學課程中,我們會先簡短比較並對照相互關聯的子查詢和 JOIN,再探索如何建立 TableAdapter,在其主查詢中包含 JOIN

比較並對照相互關聯的子查詢和 JOIN

回想一下,在第一個教學課程中的 Northwind DataSet 中建立的 ProductsTableAdapter 使用相互關聯的子查詢來傳回每個產品的相對應類別和供應商名稱。 ProductsTableAdapter 的主查詢如下所示。

SELECT ProductID, ProductName, SupplierID, CategoryID, 
       QuantityPerUnit, UnitPrice, UnitsInStock, UnitsOnOrder, 
       ReorderLevel, Discontinued,
       (SELECT CategoryName FROM Categories WHERE Categories.CategoryID = 
            Products.CategoryID) as CategoryName, 
       (SELECT CompanyName FROM Suppliers WHERE Suppliers.SupplierID = 
            Products.SupplierID) as SupplierName
FROM Products

兩個相互關聯的子查詢 - (SELECT CategoryName FROM Categories WHERE Categories.CategoryID = Products.CategoryID)(SELECT CompanyName FROM Suppliers WHERE Suppliers.SupplierID = Products.SupplierID) - 是 SELECT 查詢,會傳回每個產品的單一值做為外部 SELECT 陳述式的資料行清單中的額外資料行。

或者,可以使用 JOIN 傳回每個產品的供應商和類別名稱。 下列查詢會傳回與上述相同的輸出,但使用 JOIN 來取代子查詢:

SELECT ProductID, ProductName, Products.SupplierID, Products.CategoryID, 
       QuantityPerUnit, UnitPrice, UnitsInStock, UnitsOnOrder, 
       ReorderLevel, Discontinued,
       Categories.CategoryName, 
       Suppliers.CompanyName as SupplierName
FROM Products
    LEFT JOIN Categories ON
        Categories.CategoryID = Products.CategoryID
    LEFT JOIN Suppliers ON
        Suppliers.SupplierID = Products.SupplierID

JOIN 會根據一些準則,將某個資料表中的記錄與另一個資料表中的記錄合併。 例如,在上述查詢中,LEFT JOIN Categories ON Categories.CategoryID = Products.CategoryID 指示 SQL Server 將每個產品記錄與其 CategoryID 值符合產品 CategoryID 值之類別記錄相合併。 合併的結果可讓我們處理每個產品的相對應類別欄位 (例如 CategoryName)。

注意

從關聯式資料庫查詢資料時,通常會使用 JOIN。 如果您不熟悉 JOIN 語法,或需要稍微複習一下其使用方式,我建議 W3 SchoolsSQL 連結教學課程。 同樣值得閱讀的是 SQL 線上叢書JOIN基本概念子查詢基本概念章節。

由於 JOIN 和相互關聯的子查詢都可以用來擷取其他資料表的相關資料,因此許多開發人員多有疑惑並且想知道要使用哪種方法。 與我交談過的所有 SQL 大師,意見都大致相同,那就是這就效能方面來說並不重要,因為 SQL Server 會產生大致相同的執行計劃。 他們而後的建議是使用您和您的團隊最熟悉的技術。 值得指出的是,在給予此建議後,這些專家隨即表示,比起相互關聯子查詢,他們更偏好 JOIN

使用具類型的 DataSet 建置資料存取層時,使用子查詢搭配工具比較適當。 特別是,如果主查詢包含任何 JOIN,則 TableAdapter 精靈將不會自動產生相對應的 INSERTUPDATEDELETE 陳述式,但會在使用相互關聯的子查詢時自動產生這些陳述式。

若要探索此缺點,請在 ~/App_Code/DAL 資料夾中建立暫時具類型的 DataSet。 在 TableAdapter 組態精靈期間,選擇使用臨機操作 SQL 陳述式並輸入下列 SELECT 查詢 (見 [圖 1]):

SELECT ProductID, ProductName, Products.SupplierID, Products.CategoryID, 
       QuantityPerUnit, UnitPrice, UnitsInStock, UnitsOnOrder, 
       ReorderLevel, Discontinued,
       Categories.CategoryName, 
       Suppliers.CompanyName as SupplierName
FROM Products
    LEFT JOIN Categories ON
        Categories.CategoryID = Products.CategoryID
    LEFT JOIN Suppliers ON
        Suppliers.SupplierID = Products.SupplierID

顯示 [TableAdaptor 組態精靈] 視窗的螢幕擷取畫面,其中已輸入包含 JOIN 的查詢。

圖 1:輸入包含 JOIN 的主查詢 (按一下以檢視完整大小的影像)

根據預設,TableAdapter 會根據主查詢自動建立 INSERTUPDATEDELETE 陳述式。 如果您按一下 [進階] 按鈕,可以看到此功能已啟用。 儘管有此設定,但 TableAdapter 將無法建立 INSERTUPDATEDELETE 陳述式,因為主查詢包含 JOIN

顯示 [進階選項] 視窗的螢幕擷取畫面,其中已選取 [產生插入、更新和刪除陳述式] 核取方塊。

圖 2:輸入包含 JOIN 的主查詢

按一下 [完成] 以完成程序。 此時,您的 DataSet 設計工具將包含單一 TableAdapter,並且有一個 DataTable,其中對於 SELECT 查詢的資料行清單中傳回的每個欄位都包含資料行。 這包括 CategoryNameSupplierName,如 [圖 3] 所示。

DataTable 針對資料行清單中傳回的每個欄位包含一個資料行

圖 3:DataTable 針對資料行清單中傳回的每個欄位包含一個資料行

雖然 DataTable 具有適當的資料行,但 TableAdapter 對於其 InsertCommandUpdateCommandDeleteCommand 屬性都缺少值。 若要確認這一點,請按一下設計工具中的 TableAdapter,然後移至 [屬性] 視窗。 您會在該處看到 InsertCommandUpdateCommandDeleteCommand 屬性設定為 [無] 。

InsertCommand、UpdateCommand 和 DeleteCommand 屬性設定為 [無]

圖 4InsertCommandUpdateCommandDeleteCommand 屬性設定為 (無) (按一下以檢視完整大小的影像)

為了解決這個缺點,我們可以透過 [屬性] 視窗手動提供 InsertCommandUpdateCommandDeleteCommand 屬性的 SQL 陳述式和參數。 或者,我們也可以開始先將 TableAdapter 的主查詢設定為「不」包含任何 JOIN。 這可為我們自動產生 INSERTUPDATEDELETE 陳述式。 完成精靈之後,我們可以從 [屬性] 視窗手動更新 TableAdapter 的 SelectCommand,使其包含 JOIN 語法。

雖然此方法可行,但使用臨機操作 SQL 查詢時相當脆弱,因為每當透過精靈重新設定 TableAdapter 的主查詢時,就會重新建立自動產生的 INSERTUPDATEDELETE 陳述式。 這表示,如果我們以滑鼠右鍵按一下 TableAdapter,從操作功能表中選擇 [設定],然後再次完成精靈,我們稍後進行的所有自訂都將遺失。

所幸,TableAdapter 自動產生的 INSERTUPDATEDELETE 陳述式的脆弱性,僅限於臨機操作 SQL 陳述式。 如果您的 TableAdapter 使用預存程序,您可以自訂 SelectCommandInsertCommandUpdateCommandDeleteCommand 預存程序,然後重新執行 TableAdapter 組態精靈,而不需要擔心預存程序會遭到修改。

在接下來的幾個步驟中,我們將建立 TableAdapter,一開始會使用省略任何 JOIN 的主查詢,以便自動產生相對應的插入、更新和刪除預存程序。 接著,我們將更新 SelectCommand,以便使用 JOIN 從相關資料表傳回其他資料行。 最後,我們將建立相對應的商務邏輯層類別,並示範如何在 ASP.NET 網頁中使用 TableAdapter。

步驟 1:使用簡化的主查詢建立 TableAdapter

對於本教學課程,我們將針對 NorthwindWithSprocs DataSet 中的 Employees 資料新增 TableAdapter 和具強式型別的 DataTable。 Employees 資料表包含 ReportsTo 欄位,會指定員工經理的 EmployeeID。 例如,員工 Anne Dodsworth 的 ReportTo 值為 5 ,也就是 Steven Buchanan 的 EmployeeID。 因此,Anne 向她的經理 Steven 報告。 除了報告每個員工的 ReportsTo 值之外,我們也可能想要擷取其經理的姓名。 這可以使用 JOIN 來達成。 但是,在最初建立 TableAdapter 時使用 JOIN,會防止精靈自動產生相對應的插入、更新和刪除功能。 因此,我們開始將先建立 TableAdapter,其主查詢不包含任何 JOIN。 然後,在步驟 2 中,我們將更新主查詢預存程序,透過 JOIN 擷取經理的姓名。

從開啟 ~/App_Code/DAL 資料夾中的 NorthwindWithSprocs DataSet 開始。 以滑鼠右鍵按一下設計工具,從操作功能表中選取 [新增] 選項,然後挑選 TableAdapter 功能表項。 這將啟動 [TableAdapter 組態] 精靈。 如 [圖 5] 所述,精靈會建立新的預存程序,然後按 [下一步]。 如需複習從 TableAdapter 精靈建立新預存程序的步驟,請參考針對具類型的 DataSet 的 TableAdapter 建立新的預存程序教學課程。

選取 [建立新預存程序] 選項

圖 5:選取 [建立新預存程序] 選項 (按一下以檢視完整大小的映像)

針對 TableAdapter 的主查詢使用下列 SELECT 陳述式:

SELECT EmployeeID, LastName, FirstName, Title, HireDate, ReportsTo, Country
FROM Employees

由於此查詢不包含任何 JOIN,因此 TableAdapter 精靈會以相對應的 INSERTUPDATEDELETE 陳述式自動建立預存程序,以及執行主查詢的預存程序。

下列步驟可讓我們命名 TableAdapter 的預存程序。 使用名稱 Employees_SelectEmployees_InsertEmployees_UpdateEmployees_Delete,如 [圖 6] 所示。

命名 TableAdapter 的預存程序

圖 6:命名 TableAdapter 的預存程序 (按一下以檢視完整大小的影像)

最後一個步驟會提示我們命名 TableAdapter 的方法。 使用 FillGetEmployees 做為方法名稱。 另外,務必將 [建立方法以直接將更新傳送至資料庫 (GenerateDBDirectMethods)] 保留為核取狀態。

將 TableAdapter 的方法命名為 Fill 和 GetEmployees

圖 7:命名 TableAdapter 的方法 FillGetEmployees (按一下以檢視完整大小的影像)

完成精靈之後,請花點時間檢查資料庫中的預存程序。 您應該會看到四個新的項目:Employees_SelectEmployees_InsertEmployees_UpdateEmployees_Delete。 接下來,檢查剛剛建立的 EmployeesDataTableEmployeesTableAdapter。 DataTable 對於主查詢所傳回的每個欄位都包含一個資料行。 按一下 TableAdapter,然後移至 [屬性] 視窗。 您會看到 InsertCommandUpdateCommandDeleteCommand 屬性已正確設定為呼叫相對應的預存程序。

TableAdapter 包含插入、更新和刪除功能

圖 8:TableAdapter 包含插入、更新和刪除功能 (按一下以檢視完整大小的影像)

在自動建立、更新和刪除預存程序並正確設定InsertCommandUpdateCommandDeleteCommand 屬性之後,我們就可以自訂SelectCommand 預存程序,以傳回關於每個員工的經理的其他資訊。 具體而言,我們需要更新Employees_Select 預存程序,以使用 JOIN 並傳回經理的 FirstNameLastName 值。 更新預存程序之後,我們需要更新 DataTable,使其包含這些額外的資料行。 我們將在步驟 2 和 3 中處理這兩項工作。

步驟 2:自訂預存程序以包含JOIN

開始先移至伺服器總,向下切入 Northwind 資料庫的 [預存程序] 資料夾,然後開啟 Employees_Select 預存程序。 如果您沒有看到此預存程序,請以滑鼠右鍵按一下 [預存程序] 資料夾,然後選擇 [重新整理]。 更新預存程序,讓它能夠使用 LEFT JOIN 傳回經理的名字和姓氏:

SELECT Employees.EmployeeID, Employees.LastName, 
       Employees.FirstName, Employees.Title, 
       Employees.HireDate, Employees.ReportsTo, 
       Employees.Country,
       Manager.FirstName as ManagerFirstName, 
       Manager.LastName as ManagerLastName
FROM Employees
    LEFT JOIN Employees AS Manager ON
        Employees.ReportsTo = Manager.EmployeeID

更新 SELECT 陳述式之後,移至 [檔案] 功能表並選擇 [儲存 Employees_Select] 來儲存變更。 或者,您也可以按下工具列中的 [儲存] 圖示,或按 Ctrl+S。 儲存變更之後,以滑鼠右鍵按一下伺服器總管中的 Employees_Select 預存程序,然後選擇 [執行]。 這會執行預存程序,並在 [輸出] 視窗中顯示其結果 (見 [圖 9])。

預存程序結果顯示在輸出視窗中

圖 9:預存程序結果顯示在輸出視窗中 (按一下以檢視完整大小的影像)

步驟 3:更新 DataTable s 資料行

此時,Employees_Select 預存程序傳回 ManagerFirstNameManagerLastName 值,但 EmployeesDataTable 遺漏這些資料行。 這些遺漏的資料行可以透過下列兩種方式之一新增至 DataTable:

  • 手動 - 以滑鼠右鍵按一下 DataSet 設計工具中的 DataTable,然後從 [新增] 選單中,選擇 [資料行]。 然後您可以命名該資料行,並相應地設定其屬性。
  • 自動 - TableAdapter 組態精靈會更新 DataTable 資料行,以反映預存程序所傳回的 SelectCommand 欄位。 使用臨機操作 SQL 陳述式時,精靈也會移除 InsertCommandUpdateCommandDeleteCommand 屬性,因為 SelectCommand 現在包含 JOIN。 但是,使用預存程序時,這些命令屬性會保持不變。

我們已在先前教學課程中探討手動新增 DataTable 資料行,包括使用主記錄項目符號清單搭配詳細資料 DataList 的主要/詳細資料報告上傳檔案,我們將在下一個教學課程中更詳細地探討此程序。 不過,對於本教學課程,讓我們透過 TableAdapter 組態精靈使用自動方法。

首先,以滑鼠右鍵按一下 EmployeesTableAdapter,然後從操作功能表中選取 [設定]。 這會顯示 TableAdapter 組態精靈,其中列出用來選取、插入、更新和刪除的預存程序,以及其傳回值和參數 (如果有的話)。 [圖 10] 顯示此精靈。 我們在這裡可以看到 Employees_Select 預存程序現在傳回 ManagerFirstNameManagerLastName 欄位。

精靈顯示 Employees_Select 預存程式的更新資料行清單

圖 10:精靈顯示 Employees_Select 預存程序的更新資料行清單 (按一下以檢視完整大小的影像)

按一下 [完成] 以完成精靈。 返回 DataSet 設計工具時,EmployeesDataTable 會包含兩個額外的資料行: ManagerFirstNameManagerLastName

EmployeesDataTable 包含兩個新的資料行

圖 11EmployeesDataTable 包含兩個新的資料行 (按一下以檢視完整大小的影像)

為了說明更新的 Employees_Select 預存程序已生效,而且 TableAdapter 的插入、更新和刪除功能仍然正常運作,讓我們建立一個網頁,讓使用者可以檢視和刪除員工。 不過,在我們建立這類頁面之前,必須先在商務邏輯層中建立新的類別,以便使用 NorthwindWithSprocs DataSet 中的員工。 在步驟 4 中,我們將建立一個 EmployeesBLLWithSprocs 類別。 在步驟 5 中,我們將從 ASP.NET 頁面使用此類別。

步驟 4:實作商務邏輯層

~/App_Code/BLL 資料夾中建立一個新類別檔案,名為 EmployeesBLLWithSprocs.cs。 這個類別會模擬現有 EmployeesBLL 類別的語意,不過這個新類別會提供較少的方法,並使用 NorthwindWithSprocs DataSet (而不是 Northwind DataSet)。 將下列程式碼加入 EmployeesBLLWithSprocs 類別。

using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using NorthwindWithSprocsTableAdapters;
[System.ComponentModel.DataObject]
public class EmployeesBLLWithSprocs
{
    private EmployeesTableAdapter _employeesAdapter = null;
    protected EmployeesTableAdapter Adapter
    {
        get
        {
            if (_employeesAdapter == null)
                _employeesAdapter = new EmployeesTableAdapter();
            return _employeesAdapter;
        }
    }
    [System.ComponentModel.DataObjectMethodAttribute
        (System.ComponentModel.DataObjectMethodType.Select, true)]
    public NorthwindWithSprocs.EmployeesDataTable GetEmployees()
    {
        return Adapter.GetEmployees();
    }
    [System.ComponentModel.DataObjectMethodAttribute
        (System.ComponentModel.DataObjectMethodType.Delete, true)]
    public bool DeleteEmployee(int employeeID)
    {
        int rowsAffected = Adapter.Delete(employeeID);
        // Return true if precisely one row was deleted, otherwise false
        return rowsAffected == 1;
    }
}

EmployeesBLLWithSprocs 類別的 Adapter 屬性會傳回 NorthwindWithSprocs DataSet 的 EmployeesTableAdapter 的執行個體。 這會由類別的 GetEmployeesDeleteEmployee 方法使用。 GetEmployees 方法會呼叫 EmployeesTableAdapter 相對應的 GetEmployees 方法,這個方法會叫用 Employees_Select 預存程序,並在 EmployeeDataTable 中填入其結果。 DeleteEmployee 方法同樣會呼叫 EmployeesTableAdapterDelete 方法,這個方法會叫用 Employees_Delete 預存程序。

步驟 5:使用展示層中的資料

完成 EmployeesBLLWithSprocs 類別之後,我們就可以透過 ASP.NET 頁面處理員工資料。 開啟 AdvancedDAL 資料夾中的 JOINs.aspx 頁面,並將 GridView 從 [工具箱] 拖曳至設計工具,將其 ID 屬性設定為 Employees。 接下來,從 GridView 的智慧標記,將方格繫結至名為 EmployeesDataSource的新 ObjectDataSource 控制項。

將 ObjectDataSource 設定為使用 EmployeesBLLWithSprocs 類別,然後從 [SELECT] 和 [DELETE] 索引標籤,確定已從下拉式清單中選取 GetEmployeesDeleteEmployee 方法。 按一下 [完成] 以完成 ObjectDataSource 的組態。

將 ObjectDataSource 設定為使用 EmployeesBLLWithSprocs 類別

圖 12:將 ObjectDataSource 設定為使用 EmployeesBLLWithSprocs 類別 (按一下以檢視完整大小的影像)

讓 ObjectDataSource 使用 GetEmployees 和 DeleteEmployee 方法

圖 13:讓 ObjectDataSource 使用 GetEmployeesDeleteEmployee 方法 (按一下以檢視完整大小的影像)

Visual Studio 會針對每個 EmployeesDataTable 資料行將 BoundField 新增至GridView。 移除 TitleLastNameFirstNameManagerFirstNameManagerLastName 以外的所有 BoundFields,並將最後四個 BoundFields 的 HeaderText 屬性分別重新命名為姓氏、名字、經理名字和經理姓氏。

若要允許使用者從此頁面刪除員工,我們需要執行兩件事。 首先,藉由從其智慧標記中核取 [啟用刪除] 選項,指示 GridView 提供刪除功能。 其次,將 ObjectDataSource 的 OldValuesParameterFormatString 屬性從 ObjectDataSource 精靈設定的值 (original_{0}) 變更為其預設值 ({0})。 進行這些變更之後,您的 GridView 和 ObjectDataSource 宣告式標記看起來應該如下所示:

<asp:GridView ID="Employees" runat="server" AutoGenerateColumns="False" 
    DataKeyNames="EmployeeID" DataSourceID="EmployeesDataSource">
    <Columns>
        <asp:CommandField ShowDeleteButton="True" />
        <asp:BoundField DataField="Title" 
            HeaderText="Title" 
            SortExpression="Title" />
        <asp:BoundField DataField="LastName" 
            HeaderText="Last Name" 
            SortExpression="LastName" />
        <asp:BoundField DataField="FirstName" 
            HeaderText="First Name" 
            SortExpression="FirstName" />
        <asp:BoundField DataField="ManagerFirstName" 
            HeaderText="Manager's First Name" 
            SortExpression="ManagerFirstName" />
        <asp:BoundField DataField="ManagerLastName" 
            HeaderText="Manager's Last Name" 
            SortExpression="ManagerLastName" />
    </Columns>
</asp:GridView>
<asp:ObjectDataSource ID="EmployeesDataSource" runat="server" 
    DeleteMethod="DeleteEmployee" OldValuesParameterFormatString="{0}" 
    SelectMethod="GetEmployees" TypeName="EmployeesBLLWithSprocs">
    <DeleteParameters>
        <asp:Parameter Name="employeeID" Type="Int32" />
    </DeleteParameters>
</asp:ObjectDataSource>

透過瀏覽器瀏覽頁面來測試該頁面。 如 [圖 14] 所示,頁面會列出每位員工及其經理的姓名 (假設他們有一個)。

Employees_Select 預存程序中的 JOIN 會傳回經理的姓名

圖 14Employees_Select 預存程式序中的 JOIN 傳回經理的姓名 (按一下以檢視完整大小的影像)

按一下 [刪除] 按鈕會啟動刪除工作流程,這會在 Employees_Delete 預存程序執行時達到最高點。 然而,預存程序中嘗試的 DELETE 陳述式因為外部鍵條件約束而失敗 (見 [圖 15])。 具體來說,每個員工在 Orders 資料表中都有一或多筆記錄,導致刪除失敗。

刪除具有相對應訂單的員工會導致外部鍵條件約束

圖 15:刪除具有相對應訂單的員工會導致外部鍵條件約束 (按一下以檢視完整大小的影像)

若要允許刪除員工,您可以:

  • 更新外部鍵條件約束以串聯刪除,
  • Orders 資料表手動刪除您想要刪除之員工的記錄,或
  • 更新 Employees_Delete 預存程序,先刪除 Orders 資料表中的相關記錄,再刪除 Employees 記錄。 我們在針對具類型的 DataSet 的 TableAdapter 使用現有預存程序教學課程中已經討論過這個方法。

我把這留作讀者練習之用。

摘要

使用關聯式資料庫時,查詢通常會從多個相關資料表提取其資料。 相互關聯的子查詢和 JOIN 提供兩種不同的方法,用於查詢中從相關資料表存取資料。 在先前的教學課程中,我們最常使用相互關聯的子查詢,因為 TableAdapter 無法針對涉及 JOIN 的查詢自動產生 INSERTUPDATEDELETE 陳述式。 雖然可以手動提供這些值,但當使用臨機操作 SQL 陳述式時,在 TableAdapter 組態精靈完成時將會覆寫任何自訂。

所幸,使用預存程序建立的 TableAdapter 不如使用臨機操作 SQL 陳述式所建立般的脆弱。 因此,建立 TableAdapter 是可行的,在使用預存程序時其主查詢會使用 JOIN。 在本教學課程中,我們已了解如何建立這類 TableAdapter。 我們開始先針對該 TableAdapter 主查詢使用沒有 JOINSELECT 查詢,以便自動建立相對應的插入、更新和刪除預存程序。 當 TableAdapter 完成初始組態時,我們擴增了 SelectCommand 預存程序,以使用 JOIN 並重新執行 TableAdapter 組態精靈來更新 EmployeesDataTable 的資料行。

重新執行 TableAdapter 組態精靈會自動更新 EmployeesDataTable 資料行,以反映 Employees_Select 預存程序傳回的資料欄位。 或者,我們可以手動將這些資料行新增至 DataTable。 我們將在下一個教學課程中探索手動新增資料行至 DataTable。

祝您程式設計愉快!

關於作者

Scott Mitchell,七本 ASP/ASP.NET 書籍的作者和 4GuysFromRolla.com 創始人,自 1998 年以來便開始使用 Microsoft Web 技術。 Scott 擔任獨立顧問、講師和作家。 他的新書是 Sams Teach Yourself ASP.NET 2.0 in 24 Hours。 您可以透過 mitchell@4GuysFromRolla.com 或他的部落格 (可以在 http://ScottOnWriting.NET 找到) 與他聯繫。

特別感謝

本教學課程系列已經過許多熱心的檢閱者檢閱。 本教學課程的主要檢閱者是 Hilton Geisenow、David Suru 和 Teresa Murphy。 有興趣檢閱我即將推出的 MSDN 文章嗎? 如果有,請發信到 mitchell@4GuysFromRolla.com 。