*
   原稿 (英文)

Microsoft Application Blocks for .NET

Data Access Application Block 概觀

作者:Chris Brooks、Graeme Malcolm、Alex Mackman、Edward Jezierski
Microsoft Corporation

2002 年 4 月

摘要:Data Access Application Block 是一個 .NET 元件,它包含最佳化資料存取碼,可以幫助您呼叫預存程序,和針對 SQL Server 資料庫發出 SQL 文字命令。它可以傳回 SqlDataReader、DataSet 和 XmlReader 物件。您可以使用它作為自己 .NET 應用程式中的建置組塊,以減少您所需要建立、測試和維護的自訂程式碼數量。下載檔案內提供了完整的 C# 和 Visual Basic .NET 原始程式碼以及完整的說明文件。(列印共 15 頁)

簡介

您是否有參與設計和開發 .NET 應用程式的資料存取碼?您是否曾覺得好像一直在重複撰寫相同的資料存取碼?您是否曾在 Helper 函式中包裝資料存取碼,以便在單一行程式碼中即可呼叫預存程序?如果答案為「是」,則 Microsoft® Data Access Application Block for .NET 正適合您。

Data Access Application Block 將用於存取 Microsoft SQL Server™ 資料庫之效能和資源管理的最佳措施結合在一起。您可以在自己的 .NET 應用程式中,使用它作為建置組塊。使用它,可減少您所需建立、測試和維護的自訂程式碼數量。

尤其,Data Access Application Block 可幫助您:

  • 呼叫預存程序或 SQL 文字命令。
  • 指定參數詳細資料。
  • 傳回 SqlDataReader、DataSet 或 XmlReader 物件。

例如,在參照 Data Access Application Block 的應用程式中,您可以呼叫預存程序並在單一行程式碼內產生 DataSet,如下所示:

[Visual Basic]
Dim ds As DataSet = SqlHelper.ExecuteDataset( _
      connectionString, _
      CommandType.StoredProcedure, _
      "getProductsByCategory", _
      new SqlParameter("@CategoryID", categoryID))
 
[C#]
DataSet ds = SqlHelper.ExecuteDataset( 
      connectionString,
      CommandType.StoredProcedure,
      "getProductsByCategory",
      new SqlParameter("@CategoryID", categoryID)); 
  
  
注意   Application Block for .NET 的設計,係參考成功的 .NET 應用程式的結果。它是以原始程式碼提供,您可依現狀使用它,或針對自己的應用程式加以自訂,但它並非 Microsoft ADO.NET 程式庫未來方向的指標;Microsoft ADO.NET 程式庫是為了各種使用情況下,精準地控制資料存取行為而建置的。對此情況,ADO.NET 的未來版次可能以不同模型來解決。

本概觀的其餘部份,分成下列幾節:

Data Access Application Block 包含哪些內容?

下載和安裝 Data Access Application Block

使用 Data Access Application Block

內部設計

常見問題集

意見和支援

共同合作者

Data Access Application Block 包含哪些內容?

所提供的 Data Access Application Block 原始程式碼以及「快速啟動」範例應用程式,可讓您用來測試其功能。Data Access Application Block 也包含完整的說明文件,以幫助您使用和了解提供的程式碼。

Visual Studio .NET 專案

其中提供了 Data Access Application Block 的 Microsoft Visual Basic® .NET 和 Microsoft Visual C#™ 原始程式碼,以及每一種語言的「快速啟動範例」用戶端應用程式,供您用來測試一般案例。這有助於增加您對 Data Access Application Block 如何運作的了解。您也可以依照個人需求,自訂原始程式碼。

每一個 Visual Basic 和 C# Microsoft.ApplicationBlocks.Data 專案,均可編譯、產生一個叫作 Microsoft.ApplicationBlocks.Data.dll 的組件。此組件包括一個叫作 SqlHelper 的類別,它包含執行資料庫命令的核心功能,組件內還含有一個叫作 SqlhelperParameterCache 的次要類別,能提供參數探索和快取功能。

說明文件

Data Access Application Block 的說明文件包括下列主要章節:

  • 使用 Data Access Application Block 開發應用程式:本節包括快速啟動範例,涵蓋各種常用案例,幫助您快速入門,輕鬆使用 Data Access Application Block。
  • Data Access Application Block 的設計和實作:本節包括背景設計原理資訊,提供對 Data Access Application Block 設計和實作的深入探討。
  • 部署和作業:本節包括安裝資訊,內含部署和更新選項,以及安全性相關資訊。
  • 參考資訊:這一節包含廣泛的 API 參考資訊,詳述構成 Data Access Application Block 的類別和介面。

系統需求

執行 Data Access Application Block 的各項需求如下:

  • Microsoft Windows® 2000, Windows XP Professional
  • .NET Framework SDK (英文) 的 RTM 版本
  • Visual Studio® .NET 的 RTM 版本 (建議但非必要)
  • SQL Server 7.0 或更新的資料庫伺服器

下載和安裝 Data Access Application Block

所提供的 Windows 安裝程式檔,包含已簽署的 Data Access Application Block 組件和完整的說明文件。

安裝程序會在 [程式集] 功能表上建立 [Microsoft Application Blocks for .NET] 子功能表。在 [Microsoft Application Blocks for .NET] 子功能表上,會有一個 [Data Access] 子功能表,它包括啟動說明文件和啟動 Data Access Application Block Visual Studio .NET 解決方案的選項。

請到 MSDN Downloads (英文) 開啟下載檔。

使用 Data Access Application Block

本節討論如何使用 Data Access Application Block 執行資料庫命令和管理參數。[圖 1] 說明 Data Access Application Block 的主要元素。

[圖 1] Data Access Application Block

SqlHelper 類別提供一組靜態方法,您可使用它們來對 SQL Server 資料庫執行各種不同的命令類型。

SqlHelperParameterCache 類別,提供用來改進效能的命令參數快取功能。這是供一些 Execute 方法做內部使用 (尤其是設計為只執行預存程序的覆寫方法)。它也可以直接由資料存取用戶端使用,以快取特定命令的特定參數集。

利用 SqlHelper 類別執行命令

SqlHelper 類別提供五個 Shared (Visual Basic) 或 static (C#) 方法,叫作 ExecuteNonQueryExecuteDatasetExecuteReaderExecuteScalarExecuteXmlReader。每一個實作的方法,均提供一組一致的多載。如此,提供了一個定義完善的模式,使用 SqlHelper 類別來執行命令,而同時又讓開發人員選擇存取資料的方式時,有必要的彈性。針對每一個方法提供的多載,均支援不同的方法引數,使開發人員可以決定如何傳遞連線、交易和參數資訊。在類別中實作的所有方法,均支援下列多載:

[Visual Basic]
Execute* (ByVal connection As SqlConnection, _
          ByVal commandType As CommandType, _
          ByVal CommandText As String)

Execute* (ByVal connection As SqlConnection, _
          ByVal commandType As CommandType, _
          ByVal commandText As String, _
          ByVal ParamArray commandParameters() As SqlParameter)

Execute* (ByVal connection As SqlConnection, _
          ByVal spName As String, _
          ByVal ParamArray parameterValues() As Object)

Execute* (ByVal transaction As SqlTransaction, _
          ByVal commandType As CommandType, _
          ByVal commandText As String)

Execute* (ByVal transaction As SqlTransaction, _
          ByVal commandType As CommandType, _
          ByVal commandText As String, _
          ByVal ParamArray commandParameters() As SqlParameter)

Execute* (ByVal transaction As SqlTransaction, _
          ByVal spName As String, _
          ByVal ParamArray parameterValues() As Object)

[C#]
Execute* (SqlConnection connection, CommandType commandType, 
          string commandText)

Execute* (SqlConnection connection, CommandType commandType,
          string commandText, params SqlParameter[] commandParameters)

Execute* (SqlConnection connection, string spName, 
          params object[] parameterValues)

Execute* (SqlConnection connection, 
          CommandType commandType, string commandText)

Execute* (SqlConnection connection,
          CommandType commandType, string commandText, 
          params SqlParameter[] commandParameters)

Execute* (SqlConnection connection,
          string spName, params object[] parameterValues)

除了這些多載之外,ExecuteXmlReader 以外的所有方法均提供多載,允許連線資訊以連線字串傳遞,而不是以連線物件傳遞,如下列方法簽章所示:

[Visual Basic]
Execute* (ByVal connectionString As String, _
          ByVal commandType As CommandType, _
          ByVal commandText As String)

Execute* (ByVal connectionString As String, _
          ByVal commandType As CommandType, _
          ByVal commandText As String, _
          ByVal ParamArray commandParameters() As SqlParameter)

Execute* (ByVal connectionString As String, _
          ByVal spName As String, _
          ByVal ParamArray parameterValues() As Object)

[C#]
Execute* (string connectionString, CommandType commandType, 
          string commandText)

Execute* (string connectionString, CommandType commandType, 
          string commandText, 
          params SqlParameter[] commandParameters)

Execute* (string connectionString, string spName, 
          params object[] parameterValues)
注意    由於 ExecuteXmlReaderSqlDataReader 物件不一樣,當 XmlReader 關閉時,XmlReader 物件並不提供自動關閉連線的方式,故不支援連線字串。已傳遞連線字串的用戶端,使用完與 XmlReader 相關聯的連線物件後,則無法關閉該物件。

您可以撰寫使用任何 SqlHelper 類別方法的程式碼,方法很簡單,只要參照 Data Access Application Block 組件,並匯入 Microsoft.ApplicationBlocks.Data 命名空間即可,如下列程式碼範例所示。

[Visual Basic]
Imports Microsoft.ApplicationBlocks.Data

[C#]
using Microsoft.ApplicationBlocks.Data;
  

在匯入命名空間之後,您就可以呼叫任何 Execute* 方法,如下列程式碼範例所示。

[Visual Basic]
Dim ds As DataSet = SqlHelper.ExecuteDataset( _
   "SERVER=(local);DATABASE=Northwind;INTEGRATED SECURITY=True;",
     _
   CommandType.Text, "SELECT * FROM Products")

[C#]
DataSet ds = SqlHelper.ExecuteDataset( 
   "SERVER=DataServer;DATABASE=Northwind;INTEGRATED
     SECURITY=sspi;", _
   CommandType.Text, "SELECT * FROM Products");

使用 SqlHelperParameterCache 類別來管理參數

SqlHelperParameterCache 類別,提供可用來管理參數的三個公用、共用方法。這些方法如下:

  • CacheParameterSet:用來儲存一個 SqlParameters 陣列到快取區。
  • GetCachedParameterSet:用來擷取一個快取參數陣列的複本。
  • GetSpParameterSet:一種多載方法,藉由查詢一次資料庫再快取其結果供未來查詢之用,來擷取某個指定預存程序的適當參數。

快取和擷取參數

可使用 CacheParameterSet 方法,來快取 SqlParameter 物件的陣列。此方法結合連線字串和命令文字來建立機碼,然後將參數陣列儲存在 Hashtable 中。

若要從快取區擷取參數,則使用 GetCachedParameterSet 方法。此方法會傳回 SqlParameter 物件陣列,這些物件以快取區中、對應傳遞至該方法的連線字串和命令文字的參數之名稱、值、資料導向、資料型別...等等加以初始化。

注意   作為參數集之機碼的連線字串,會用簡單字串的比較方式進行比對。從 GetCachedParameterSet 擷取參數的連線字串,必須與使用 CacheParameterSet 來儲存那些參數的連線字串完全相同。語法不同的連線字串,即使語意相當,也不會造成完全相符。

下列程式碼顯示如何使用 SqlHelperParameterCache 類別來快取和擷取 Transact-SQL 陳述式的參數

[Visual Basic]
'初始化連線字串和命令文字
'這些將形成用來儲存和擷取參數的機碼
Const CONN_STRING As String = _
  "SERVER=(local); DATABASE=Northwind; INTEGRATED SECURITY=True;"
Dim sql As String = _
       "SELECT ProductName FROM Products " + _
       "WHERE Category=@Cat AND SupplierID = @Sup"

'快取參數
Dim paramsToStore(1) As SqlParameter
paramsToStore(0) = New SqlParameter("@Cat", SqlDbType.Int)
paramsToStore(1) = New SqlParameter("@Sup", SqlDbType.Int)
SqlHelperParameterCache.CacheParameterSet(CONN_STRING, _
                                          sql, _
                                          paramsToStore)

'從快取區擷取參數
Dim storedParams(1) As SqlParameter
storedParams = SqlHelperParameterCache.GetCachedParameterSet( _
                                                 CONN_STRING, sql)
storedParams(0).Value = 2
storedParams(1).Value = 3

'在命令中使用參數
Dim ds As DataSet
ds = SqlHelper.ExecuteDataset(CONN_STRING, _
                              CommandType.Text, _
                              sql, storedParams)

[C#]
// 初始化連線字串和命令文字
// 這些將形成用來儲存和擷取參數的機碼
const string CONN_STRING =
  "SERVER=(local); DATABASE=Northwind; INTEGRATED SECURITY=True;";
string spName = "SELECT ProductName FROM Products " + 
                "WHERE Category=@Cat AND SupplierID = @Sup";

//快取參數
SqlParameter[] paramsToStore = new SqlParameter[2];
paramsToStore[0] = New SqlParameter("@Cat", SqlDbType.Int);
paramsToStore[1] = New SqlParameter("@Sup", SqlDbType.Int);
SqlHelperParameterCache.CacheParameterSet(CONN_STRING, 
                                          sql, 
                                          paramsToStore);

//從快取區擷取參數
SqlParameter storedParams = new SqlParameter[2];
storedParams = SqlHelperParameterCache.GetCachedParameterSet(
                                              CONN_STRING, sql);
storedParams(0).Value = 2;
storedParams(1).Value = 3;

//在命令中使用參數
DataSet ds;
ds = SqlHelper.ExecuteDataset(CONN_STRING, 
                              CommandType.StoredProcedure,
                              sql, storedParams);

擷取預存程序的參數

SqlHelperParameterCache 亦提供擷取某特定預存程序之參數陣列的方式。提供此功能的多載方法,名稱叫作 GetSpParameterSet 且含有兩項實作。本方法會嘗試從快取區擷取指定預存程序的參數。若未快取參數,則會使用 .NET SqlCommandBuilder 類別、從內部擷取它們,並新增至快取區供後續要求使用。然後,當陣列中的參數傳回用戶端之前,會對每一個參數指定適當的參數設定。下列程式碼顯示如何擷取 Northwind 資料庫中、SalesByCategory 預存程序的參數。

[Visual Basic]
'初始化連線字串和命令文字
'這些將形成用來儲存和擷取參數的機碼
Const CONN_STRING As String = _
  "SERVER=(local); DATABASE=Northwind; INTEGRATED SECURITY=True;"
Dim spName As String = "SalesByCategory"

'擷取參數
Dim storedParams(1) As SqlParameter
storedParams = SqlHelperParameterCache.GetSpParameterSet( _
                                          CONN_STRING, spName)
storedParams(0).Value = "Beverages"
storedParams(1).Value = "1997"

'在命令中使用參數
Dim ds As DataSet
ds = SqlHelper.ExecuteDataset(CONN_STRING, _
                              CommandType.StoredProcedure, _
                              spName, storedParams)

[C#]
// 初始化連線字串和命令文字
// 這些將形成用來儲存和擷取參數的機碼
const string CONN_STRING = 
  "SERVER=(local); DATABASE=Northwind; INTEGRATED SECURITY=True;";
string spName = "SalesByCategory";

// 擷取參數
SqlParameter storedParams = new SqlParameter[2];
storedParams = SqlHelperParameterCache.GetSpParameterSet(
                                          CONN_STRING, spName);
storedParams[0].Value = "Beverages";
storedParams[1].Value = "1997";

//在命令中使用參數
DataSet ds;
ds = SqlHelper.ExecuteDataset(CONN_STRING, 
                              CommandType.StoredProcedure,
                              spName, storedParams);

內部設計

Data Access Application Block 包含完整的原始程式碼,以及與其設計有關的綜合指南。本節描述主要實作的詳細資料。

SqlHelper 類別實作詳細資料

SqlHelper 類別的設計,是要透過一組靜態函式來結合資料存取功能。因為它不是設計成要繼承或執行個體化,所以該類別是宣告為含有 Non-inheritable 類別的私用建構函式。

每一個在 SqlHelper 類別中實作的方法,均提供一組一致的多載。這利用 SqlHelper 類別提供一個定義完善的模式來執行命令,同時讓開發人員在選擇存取資料的方式時,有所需的彈性。針對每一個方法提供的多載,均支援不同的方法引數,使開發人員可以決定如何傳遞連線、交易和參數資訊。SqlHelper 類別中實作的方法如下:

  • ExecuteNonQuery:此方法是用來執行不傳回任何列或值的命令。它們通常用來執行資料庫更新,但也可以用來傳回預存程序中的輸出參數。
  • ExecuteReader:此方法是用來傳回 SqlDataReader 物件,它包含命令傳回的結果集 (Resultset)。
  • ExecuteDataset:此方法會傳回 DataSet 物件,它包含命令傳回的結果集 (Resultset)。
  • ExecuteScalar:此方法會傳回單一值。此值一定是命令傳回的第一列的第一欄。
  • ExecuteXmlReader:此方法會從 FOR XML 查詢傳回 XML 片段。

除了公用方法之外,SqlHelper 類別還包含一些私用函式,用來管理參數和為命令的執行做準備。不論用戶端呼叫的方法實作為何,所有命令都是使用 SqlCommand 物件來執行。在可以執行此 SqlCommand 物件之前,任何參數必須新增至它的 Parameters 集合,且 ConnectionCommandTypeCommandTextTransaction 屬性必須設定正確。SqlHelper 類別中的私用函式,主要是設計來提供一致的方式,對 SQL Server 資料庫執行命令,而不論用戶端應用程式呼叫何種多載方法實作。SqlHelper 類別中的私用公用程式函式如下:

  • AttachParameters:此函數是用來將任何必要的 SqlParameter 物件附加至所要執行的 SqlCommand。
  • AssignParameterValues:此函數是用來指定 SqlParameter 物件的值。
  • PrepareCommand:此函數是用來初始化命令屬性,例如它的連線、交易內容...等等。
  • ExecuteReader:這個私用的 ExecuteReader 實作,是用來開啟具備適當的 CommandBehavior 的 SqlDataReader 物件,以便以最有效率的方式、管理與讀取器相關聯的連線之存留期。

SqlHelperParameterCache 類別實作詳細資料

參數陣列是在私用 Hashtable 中快取。從快取區擷取的參數會從內部被複製,使用戶端應用程式得以變更參數值,而不影響快取的參數陣列。有一個叫作 CloneParameters 的私用共用函數,即作為此用途。

常見問題集

這一版新增了哪些功能?

Data Access Application Block 的 RTM 版次,包含下列新功能,以及 Beta 2.0 版次之後的一些變更:

  • SqlHelper 類別方法的異動多載,不再需要 SqlConnection 參數。在這一版,連線資訊是衍生自 SqlTransaction 物件,因此不必在方法簽章中包含 SqlConnection 物件參數。
  • 現在 GetSpParameterSet 方法使用 ADO.NET CommandBuilder 類別的 DeriveParameters 方法,來確定預存程序需要的參數。這比 Beta 2.0 版次所使用的技巧更有效率,因為之前是直接查詢資料庫來擷取資訊。

我可以使用 XCOPY 的部署方式,來部署 Data Access Application Block 組件嗎?

可以。編譯之後,Microsoft 的 ApplicationBlocks.Data.dll 組件就可利用 XCOPY 部署。

何時該使用 ExecuteDataset 方法,而何時該使用 ExecuteReader 方法?

問題的關鍵,在於您何時該傳回 DataSet 物件中的多重資料列,以及何時該使用 DataReader。答案取決於您應用程式的需求,以及彈性和效能之間的取捨。DataSet 讓您以彈性的、中斷的、關聯的方式來檢視資料,而 DataReader 則提供極高的效能、唯讀、順向的資料指標。關於 DataSet 和 DataReader 的全面性比較,請參閱《Data Access Architecture Guide (英文)》。

我如何使用 ExecuteDataset 傳回包含多重表格的 DataSet?

您可以建立會傳回多重資料列集的預存程序 (透過執行多重 SELECT 陳述式或對其他預存程序發出巢狀呼叫),並使用 ExecuteDataset 方法執行它,來擷取包含多重表格的 DataSet。

例如,假設您的資料庫中有下列預存程序。

CREATE PROCEDURE GetCategories
AS
SELECT * FROM Categories
GO
CREATE PROCEDURE GetProducts
AS
SELECT * FROM Products
  

您就可以建立一個主要預存程序,對上述這些程序發出巢狀呼叫,如下列程式碼範例所示。

CREATE PROCEDURE GetCategoriesAndProducts
AS
BEGIN
  EXEC GetCategories
  EXEC GetProducts
END
  

以 ExecuteDataset 方法執行這個主要預存程序,就會傳回包含兩個表格的單一 DataSet;一個包含分類資料,另一個包含產品資料。

注意   ExecuteDataset 方法,無法讓您自訂所傳回表格的名稱。第一個表格一律編號為 0 並命名為 Table,第二個表格編號為 1 並命名為 Table1,依此類推。

還有其他應用程式區塊嗎?

Data Access Application Block 是目前發行的數個 Application Blocks 的其中之一。這些 Application Blocks 解決開發人員在各個專案所面臨的常見問題。它們可以快速而容易地插入 .NET 應用程式中。

意見和支援

您有問題或意見與建議嗎?若要提供關於 Data Access Application Block 的建議,請傳送電子郵件訊息至 devfdbck@microsoft.com

Application Blocks for .NET 是為了要帶動 .NET 分散式應用程式的開發而設計的。範例程式碼和說明文件均「依現狀」提供。雖然它已通過測試且被視為健全的程式碼集,但它不像傳統 Microsoft 產品一樣享有技術支援。

我們也建立了新聞群組,以協助您使用 Application Blocks for .NET。請利用此新聞群組,在線上和志同道合的人士、朋友以及 Microsoft 支援中心專業人員們,一同進行公開討論。

別人可以從您的問題和意見中受惠,而我們的開發團隊每天都會監督新聞群組:
Newsgroup: Web-Based Reader
http://msdn.microsoft.com/newsgroups/loadframes.asp?icp=msdn&slcid=us&newsgroup=microsoft.public.dotnet.distributed_apps (英文)

Newsgroup: NNTP Reader
news://msnews.microsoft.com/microsoft.public.dotnet.distributed_apps (英文)

您想要學習和利用 .NET 的超強功能嗎?請造訪 Microsoft Technology Center,即可與技術專家們並肩作業、學習開發程式的最佳準則。有關其他詳細資訊,請造訪 http://www.microsoft.com/business/services/mtc.asp (英文)。

需要進一步協助嗎?請看看支援服務的最新單元:Advisory Services,這是符合小型諮詢需求的積極式解決方案。如需 Advisory Services 的其他詳細資訊,請造訪 http://support.microsoft.com/default.aspx?id=fh;EN-US;advisoryservice (英文)。

相關資訊

Data Access Application Block 的設計和開發,是依據 Data Access in .NET Architecture Guide (英文) 所述的最佳準則和一般設計原則。閱讀該手冊可進一步了解資料存取。

共同合作者

感謝下列共同合作者和校閱者:Susan Warren、Brad Abrams、Andy Dunn、Michael Day、Mark Ashton、Gregory Leake、Steve Busby、Kenny Jones、David Schleifer、Andrew Roubin (Vorsite Corp.)、Jeffrey Richter (Wintellect)、Bernard Chen (Sapient) 和 Matt Drucker (Turner Broadcasting)。

同時感謝內容編寫團隊:Tina Burden (Entirenet)、Shylender Ramamurthy (Infosys Technologies Ltd) 和 Filiberto Selvas Patino。