設定資料存取層的連線和命令層級設定 (C#)
具型別數據集內的 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
。 若要對資料庫發出 INSERT
、 UPDATE
、 DELETE
或 SELECT
命令,請使用 SqlCommand
類別。
除了在交易中包裝資料庫修改教學課程之外,我們不需要自行撰寫任何低階 ADO.NET 程式代碼,因為 TableAdapters 自動產生的程式代碼包含連接到資料庫、發出命令、擷取數據,並將該數據填入 DataTables 所需的功能。 不過,有時可能需要自定義這些低階設定。 在接下來的幾個步驟中,我們將探討如何點選 TableAdapters 內部使用的 ADO.NET 物件。
步驟 1:使用 Connection 屬性檢查
每個 TableAdapter 類別都有一個 Connection
屬性,可指定資料庫連接資訊。 此屬性的數據類型和 ConnectionString
值是由 TableAdapter 組態精靈中所做的選取專案所決定。 回想一下,當我們第一次將 TableAdapter 新增至具類型的數據集時,此精靈會要求我們提供資料庫來源 (請參閱圖 1) 。 第一個步驟中的下拉式清單包含組態檔中指定的資料庫,以及伺服器總管數據 Connections的任何其他資料庫。 如果我們想要使用的資料庫不存在於下拉式清單中,可以按兩下 [新增連接] 按鈕並提供所需的連線資訊來指定新的資料庫連接。
圖 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
等於 null
。 Connection
存取屬性時,它會先檢查成員變數是否已_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
的專案中建立新的子資料夾。
圖 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
。
圖 4: Connection
可透過 ConnectionModifier
屬性設定屬性的輔助功能層級 (按兩下即可檢視完整大小的影像)
儲存 DataSet,然後返回 ProductsBLL
類別。 如前所述,移至其中一個現有的方法並輸入 , Adapter
然後叫用句號索引鍵來啟動 IntelliSense。 清單應該包含 Connection
屬性,這表示您現在可以以程序設計方式從 BLL 讀取或指派任何連線層級設定。
步驟 3:檢查 Command-Related 屬性
TableAdapter 是由預設自動產生的 INSERT
、 UPDATE
和 DELETE
語句的主要查詢所組成。 這個主要查詢 、 INSERT
UPDATE
和 DELETE
語句會透過 Adapter
屬性,在 TableAdapter 程式代碼中實作為 ADO.NET 數據配接器物件。 就像其 Connection
屬性一樣, Adapter
屬性的數據類型是由所使用的數據提供者所決定。 因為這些教學課程使用 SqlClient 提供者, Adapter
所以 屬性的類型為 SqlDataAdapter
。
TableAdapter s Adapter
屬性有三個類型 SqlCommand
屬性,可用來發出 INSERT
、 UPDATE
和 DELETE
語句:
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 可以有多個命令物件 ,也就是 InsertCommand
、 UpdateCommand
和 DeleteCommand
,以及屬性中的 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 實例的所有命令問題設定命令逾時。
注意
Adapter
和 CommandCollection
屬性會標示為 private
,這表示只能從 TableAdapter 內的程式代碼存取它們。 Connection
不同於 屬性,這些存取修飾詞無法設定。 因此,如果您需要將命令層級屬性公開至架構中的其他層,您必須使用上述的部分類別方法,提供 public
讀取或寫入 private
命令物件的方法或屬性。
摘要
具型別數據集內的 TableAdapters 可用來封裝數據存取詳細數據和複雜度。 使用 TableAdapters,我們不需要擔心撰寫 ADO.NET 程式代碼來連線到資料庫、發出命令,或將結果填入 DataTable。 這一切都會自動為我們處理。
不過,有時可能需要自定義低階 ADO.NET 細節,例如變更 連接字串 或默認連線或命令逾時值。 TableAdapter 具有自動產生的 Connection
、 Adapter
和 CommandCollection
屬性,但這些屬性預設為 internal
或 private
。 您可以使用部分類別擴充 TableAdapter 來包含 public
方法或屬性,來公開此內部資訊。 或者,您可以透過 TableAdapter s 屬性來設定 TableAdapter s Connection
ConnectionModifier
屬性存取修飾詞。
快樂的程序設計!
關於作者
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。
意見反應
https://aka.ms/ContentUserFeedback。
即將登場:在 2024 年,我們將逐步淘汰 GitHub 問題作為內容的意見反應機制,並將它取代為新的意見反應系統。 如需詳細資訊,請參閱:提交並檢視相關的意見反應