共用方式為


設定資料存取層的連線和命令層級設定 (C#)

作者 :Scott Mitchell

下載 PDF

具型別數據集內的 TableAdapters 會自動處理連接到資料庫、發出命令,以及填入 DataTable 的結果。 不過,有時候我們想要自行處理這些詳細數據,在本教學課程中,我們會瞭解如何存取 TableAdapter 中的資料庫連線和命令層級設定。

簡介

在整個教學課程系列中,我們使用具類型的數據集來實作分層架構的數據存取層和商務物件。 如 第一個教學課程所述,具類型的 DataSet DataTables 可作為數據的存放庫,而 TableAdapters 會作為包裝函式來與資料庫通訊,以擷取和修改基礎數據。 TableAdapters 會封裝與使用資料庫相關的複雜度,並讓我們不必撰寫程式代碼以連線到資料庫、發出命令,或將結果填入 DataTable。

不過,有時候我們需要鑽研 TableAdapter 的深度,並撰寫可直接與 ADO.NET 物件搭配運作的程序代碼。 例如,在交易內包裝資料庫修改教學課程中,我們已將方法新增至 TableAdapter,以便開始、認可和回復 ADO.NET 交易。 這些方法使用指派給 TableAdapter 對象SqlCommand的內部手動建立SqlTransaction物件。

在本教學課程中,我們將探討如何存取 TableAdapter 中的資料庫連接和命令層級設定。 特別是,我們會將功能新增至 ProductsTableAdapter ,以存取基礎 連接字串 和命令逾時設定。

使用 ADO.NET 處理數據

Microsoft .NET Framework 包含一系列專為處理數據而設計的類別。 這些類別可在 命名空間中找到System.Data,稱為 ADO.NET 類別。 ADO.NET 下的某些類別會系結至特定數據提供者。 您可以將數據提供者視為通道,以允許資訊在 ADO.NET 類別與基礎數據存放區之間流動。 有一般化提供者,例如 OleDb 和 ODBC,以及專為特定資料庫系統設計的提供者。 例如,雖然可以使用 OleDb 提供者連線到 Microsoft SQL Server 資料庫,但 SqlClient 提供者會更有效率,因為它專為 SQL Server 而設計和優化。

以程式設計方式存取資料時,通常會使用下列模式:

  • 建立資料庫的連線。
  • 發出命令。
  • 針對 SELECT 查詢,請使用產生的記錄。

有個別的 ADO.NET 類別可用來執行每個步驟。 例如,若要使用 SqlClient 提供者連線到資料庫,請使用 類別SqlConnection。 若要對資料庫發出 INSERTUPDATEDELETESELECT 命令,請使用 SqlCommand 類別

除了在交易中包裝資料庫修改教學課程之外,我們不需要自行撰寫任何低階 ADO.NET 程式代碼,因為 TableAdapters 自動產生的程式代碼包含連接到資料庫、發出命令、擷取數據,並將該數據填入 DataTables 所需的功能。 不過,有時可能需要自定義這些低階設定。 在接下來的幾個步驟中,我們將探討如何點選 TableAdapters 內部使用的 ADO.NET 物件。

步驟 1:使用 Connection 屬性檢查

每個 TableAdapter 類別都有一個 Connection 屬性,可指定資料庫連接資訊。 此屬性的數據類型和 ConnectionString 值是由 TableAdapter 組態精靈中所做的選取專案所決定。 回想一下,當我們第一次將 TableAdapter 新增至具類型的數據集時,此精靈會要求我們提供資料庫來源 (請參閱圖 1) 。 第一個步驟中的下拉式清單包含組態檔中指定的資料庫,以及伺服器總管數據 Connections的任何其他資料庫。 如果我們想要使用的資料庫不存在於下拉式清單中,可以按兩下 [新增連接] 按鈕並提供所需的連線資訊來指定新的資料庫連接。

TableAdapter 設定精靈的第一個步驟

圖 1:TableAdapter 設定精靈的第一個步驟 (按兩下以檢視全大小映射)

讓我們花點時間檢查 TableAdapter s Connection 屬性的程序代碼。 如 建立數據存取層 教學課程所述,我們可以移至 [類別檢視] 視窗、向下切入至適當的類別,然後按兩下成員名稱,以檢視自動產生的 TableAdapter 程式代碼。

移至 [檢視] 功能表並選擇 [類別檢視] (,或輸入 Ctrl+Shift+C) ,流覽至 [類別檢視] 視窗。 從 [類別檢視] 視窗的上半部向下切入至 NorthwindTableAdapters 命名空間,然後選取 ProductsTableAdapter 類別。 這會在 [類別檢視] 的下半部顯示 ProductsTableAdapter s 成員,如圖 2 所示。 按兩下 Connection 屬性以查看其程式代碼。

按兩下類別檢視中的連接屬性,以檢視其自動產生的程式代碼

圖 2:Double-Click 類別檢視中的 Connection 屬性,以檢視其自動產生的程式代碼

TableAdapter 的 Connection 屬性和其他連接相關程序代碼如下:

private System.Data.SqlClient.SqlConnection _connection;
private void InitConnection() {
    this._connection = new System.Data.SqlClient.SqlConnection();
    this._connection.ConnectionString = 
        ConfigurationManager.ConnectionStrings["NORTHWNDConnectionString"].ConnectionString;
}
internal System.Data.SqlClient.SqlConnection Connection {
    get {
        if ((this._connection == null)) {
            this.InitConnection();
        }
        return this._connection;
    }
    set {
        this._connection = value;
        if ((this.Adapter.InsertCommand != null)) {
            this.Adapter.InsertCommand.Connection = value;
        }
        if ((this.Adapter.DeleteCommand != null)) {
            this.Adapter.DeleteCommand.Connection = value;
        }
        if ((this.Adapter.UpdateCommand != null)) {
            this.Adapter.UpdateCommand.Connection = value;
        }
        for (int i = 0; (i < this.CommandCollection.Length); i = (i + 1)) {
            if ((this.CommandCollection[i] != null)) {
                ((System.Data.SqlClient.SqlCommand)
                    (this.CommandCollection[i])).Connection = value;
            }
        }
    }
}

具現化 TableAdapter 類別時,成員變數 _connection 等於 nullConnection存取屬性時,它會先檢查成員變數是否已_connection具現化。 如果沒有,InitConnection則會叫用 方法,以具現化_connection並將其 ConnectionString 屬性設定為從 TableAdapter 組態精靈第一個步驟指定的 連接字串 值。

Connection屬性也可以指派給 SqlConnection 物件。 這麼做會將新的 SqlConnection 物件與每個 TableAdapter 對象 SqlCommand 產生關聯。

步驟 2:公開 Connection-Level 設定

線上資訊應該會持續封裝在 TableAdapter 中,而且無法供應用程式架構中的其他層存取。 不過,在某些情況下,TableAdapter 的連接層級信息必須可供查詢、使用者或 ASP.NET 頁面存取或自定義。

讓我們擴充 ProductsTableAdapter DataSet 中的 Northwind ,以包含ConnectionString商業規則層可用來讀取或變更 TableAdapter 所使用的 連接字串 屬性。

注意

連接字串 是指定資料庫連接資訊的字串,例如要使用的提供者、資料庫的位置、驗證認證和其他資料庫相關設定。 如需各種數據存放區和提供者所使用的 連接字串 模式清單,請參閱 ConnectionStrings.com

如同 建立數據存取層 教學課程中所討論,具類型的數據集自動產生的類別可以透過使用部分類別來擴充。 首先,在資料夾下方~/App_Code/DAL名為 ConnectionAndCommandSettings 的專案中建立新的子資料夾。

新增名為 ConnectionAndCommandSettings 的子資料夾

圖 3:新增名為 的子資料夾 ConnectionAndCommandSettings

新增名為 ProductsTableAdapter.ConnectionAndCommandSettings.cs 的新類別檔案,並輸入下列程式代碼:

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;
namespace NorthwindTableAdapters
{
    public partial class ProductsTableAdapter
    {
        public string ConnectionString
        {
            get
            {
                return this.Connection.ConnectionString;
            }
            set
            {
                this.Connection.ConnectionString = value;
            }
        }
    }
}

這個部分類別會將名為 ConnectionString 的屬性新增public至 類別,ProductsTableAdapter讓任何圖層讀取或更新 TableAdapter 基礎連線的 連接字串。

建立此部分類別 (並儲存) ,開啟 類別 ProductsBLL 。 移至其中一個現有的方法並輸入 Adapter ,然後叫用句號索引鍵來啟動 IntelliSense。 您應該會看到 IntelliSense 中可用的新 ConnectionString 屬性,這表示您可以從 BLL 以程式設計方式讀取或調整此值。

公開整個連接物件

這個部分類別只會公開基礎連接物件的一個屬性: ConnectionString。 如果您想要讓整個連接物件可供使用超過 TableAdapter 的範圍,您也可以變更 Connection 屬性的保護等級。 我們在步驟 1 中檢查的自動產生程式代碼顯示 TableAdapter 的 Connection 屬性標示為 internal,這表示它只能由相同元件中的類別存取。 不過,這可以透過 TableAdapter 的 ConnectionModifier 屬性來變更。

Northwind開啟 DataSet,按兩下 ProductsTableAdapter Designer 中的 ,然後流覽至 屬性視窗。 您會在這個處看到ConnectionModifier設為預設值 。 Assembly 若要讓 Connection 屬性可在具型別 DataSet 元件之外使用,請將 ConnectionModifier 屬性變更為 Public

可透過 ConnectionModifier 屬性設定連接屬性的輔助功能層級

圖 4Connection 可透過 ConnectionModifier 屬性設定屬性的輔助功能層級 (按兩下即可檢視完整大小的影像)

儲存 DataSet,然後返回 ProductsBLL 類別。 如前所述,移至其中一個現有的方法並輸入 , Adapter 然後叫用句號索引鍵來啟動 IntelliSense。 清單應該包含 Connection 屬性,這表示您現在可以以程序設計方式從 BLL 讀取或指派任何連線層級設定。

TableAdapter 是由預設自動產生的 INSERTUPDATEDELETE 語句的主要查詢所組成。 這個主要查詢 、 INSERTUPDATEDELETE 語句會透過 Adapter 屬性,在 TableAdapter 程式代碼中實作為 ADO.NET 數據配接器物件。 就像其 Connection 屬性一樣, Adapter 屬性的數據類型是由所使用的數據提供者所決定。 因為這些教學課程使用 SqlClient 提供者, Adapter 所以 屬性的類型為 SqlDataAdapter

TableAdapter s Adapter 屬性有三個類型 SqlCommand 屬性,可用來發出 INSERTUPDATEDELETE 語句:

  • InsertCommand
  • UpdateCommand
  • DeleteCommand

SqlCommand物件負責將特定查詢傳送至資料庫,並具有下列屬性:CommandText,其中包含要執行的臨機操作 SQL 語句或預存程式;以及 Parameters,這是 物件的集合SqlParameter。 如我們在建立資料存取層教學課程中所見,您可以透過 屬性視窗 自定義這些命令物件。

除了其主要查詢之外,TableAdapter 還可以包含一個變數數目的方法,在叫用時,將指定的命令分派至資料庫。 所有額外方法的主要查詢命令物件和命令對象都會儲存在 TableAdapter s CommandCollection 屬性中。

讓我們花一些時間查看 DataSet 中Northwind針對ProductsTableAdapter這兩個屬性所產生的程式代碼,以及其支援的成員變數和協助程式方法:

private System.Data.SqlClient.SqlDataAdapter _adapter;
private void InitAdapter() {
    this._adapter = new System.Data.SqlClient.SqlDataAdapter();
    
    ... Code that creates the InsertCommand, UpdateCommand, ...
    ... and DeleteCommand instances - omitted for brevity ...
}
private System.Data.SqlClient.SqlDataAdapter Adapter {
    get {
        if ((this._adapter == null)) {
            this.InitAdapter();
        }
        return this._adapter;
    }
}
private System.Data.SqlClient.SqlCommand[] _commandCollection;
private void InitCommandCollection() {
    this._commandCollection = new System.Data.SqlClient.SqlCommand[9];
    ... Code that creates the command objects for the main query and the ...
    ... ProductsTableAdapter�s other eight methods - omitted for brevity ...
}
protected System.Data.SqlClient.SqlCommand[] CommandCollection {
    get {
        if ((this._commandCollection == null)) {
            this.InitCommandCollection();
        }
        return this._commandCollection;
    }
}

CommandCollection 屬性的程式Adapter代碼會密切模擬 屬性的程序Connection代碼。 有一個成員變數會保存屬性所使用的物件。 屬性 get 存取子會先檢查,以查看對應的成員變數是否為 null。 如果是,則會呼叫初始化方法,以建立成員變數的實例,並指派核心命令相關屬性。

步驟 4:公開 Command-Level 設定

在理想情況下,命令層級信息應該會保留在數據存取層內。 不過,如果架構的其他層級需要這項資訊,則可以透過部分類別公開,就像使用連接層級設定一樣。

由於 TableAdapter 只有單 Connection 一屬性,因此公開連線層級設定的程式代碼相當簡單。 修改命令層級設定時,專案會比較複雜,因為 TableAdapter 可以有多個命令物件 ,也就是 InsertCommandUpdateCommandDeleteCommand,以及屬性中的 CommandCollection 命令物件數目可變。 更新命令層級設定時,必須將這些設定傳播到所有命令物件。

例如,假設 TableAdapter 中有一些查詢需要很長的時間才能執行。 使用 TableAdapter 執行其中一個查詢時,我們可能會想要增加命令對象的 CommandTimeout 屬性。 此屬性會指定等候命令執行的秒數,並預設為 30。

若要允許 CommandTimeout BLL 調整屬性,請使用步驟 2 中建立的部分類別檔案,將下列 public 方法新增至 ProductsDataTable () ProductsTableAdapter.ConnectionAndCommandSettings.cs

public void SetCommandTimeout(int timeout)
{
    if (this.Adapter.InsertCommand != null)
        this.Adapter.InsertCommand.CommandTimeout = timeout;
    if (this.Adapter.DeleteCommand != null)
        this.Adapter.DeleteCommand.CommandTimeout = timeout;
    if (this.Adapter.UpdateCommand != null)
        this.Adapter.UpdateCommand.CommandTimeout = timeout;
    for (int i = 0; i < this.CommandCollection.Length; i++)
        if (this.CommandCollection[i] != null)
            this.CommandCollection[i].CommandTimeout = timeout;
}

這個方法可以從 BLL 或簡報層叫用,以針對該 TableAdapter 實例的所有命令問題設定命令逾時。

注意

AdapterCommandCollection 屬性會標示為 private,這表示只能從 TableAdapter 內的程式代碼存取它們。 Connection不同於 屬性,這些存取修飾詞無法設定。 因此,如果您需要將命令層級屬性公開至架構中的其他層,您必須使用上述的部分類別方法,提供 public 讀取或寫入 private 命令物件的方法或屬性。

摘要

具型別數據集內的 TableAdapters 可用來封裝數據存取詳細數據和複雜度。 使用 TableAdapters,我們不需要擔心撰寫 ADO.NET 程式代碼來連線到資料庫、發出命令,或將結果填入 DataTable。 這一切都會自動為我們處理。

不過,有時可能需要自定義低階 ADO.NET 細節,例如變更 連接字串 或默認連線或命令逾時值。 TableAdapter 具有自動產生的 ConnectionAdapterCommandCollection 屬性,但這些屬性預設為 internalprivate。 您可以使用部分類別擴充 TableAdapter 來包含 public 方法或屬性,來公開此內部資訊。 或者,您可以透過 TableAdapter s 屬性來設定 TableAdapter s ConnectionConnectionModifier 屬性存取修飾詞。

快樂的程序設計!

關於作者

Scott Mitchell 是 1998 年以來,1998 年與 Microsoft Web 技術合作的 篇 ASP/ASP.NET 書籍和 4GuysFromRolla.com 作者。 Scott 是獨立的顧問、訓練者和作者。 他的最新書籍是 Sams 在 24 小時內自行 ASP.NET 2.0。 您可以透過mitchell@4GuysFromRolla.com部落格連到,也可以透過其部落格來存取,網址為 http://ScottOnWriting.NET

特別感謝

本教學課程系列是由許多實用的檢閱者所檢閱。 本教學課程的首席檢閱者是 Burnadette、Sren Lauritsen、Teresa Murphy 和一位 Geisenow。 想要檢閱即將推出的 MSDN 文章嗎? 如果是,請將一行放在 mitchell@4GuysFromRolla.com。