NO IMAGE

摘要:Data Access Application Block 是一個 .NET 元件,包含優化的資料訪問程式碼,可以幫助使用者呼叫儲存過程以及向 SQL Server 資料庫發出 SQL 文字命令。它返回 SqlDataReader、DataSet 和 XmlReader 物件。您可以在自己的 .NET 應用程式中將其作為構造塊來使用,以減少需要建立、測試和維護的自定義程式碼的數量。您可以下載完整的 C# 和 Visual Basic .NET 原始碼以及綜合文件。

簡介

您是否正在從事 .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 的應用程式塊)是基於對成功的 .NET 應用程式進行詳細研究而設計的。它以原始碼的形式提供,您可以原樣使用,也可以針對自己的應用程式進行自定義。該應用程式塊並不代表未來 Microsoft ADO.NET 程式庫的發展方向。Microsoft ADO.NET 程式庫是為在各種使用情況下實現對資料訪問行為的精確控制而建立的。將來的 ADO.NET 版本可能會使用不同的模型來實現這個方案

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)

注意: ExecuteXmlReader 不支援連線字串,因為:與 SqlDataReader 物件不同,XmlReader 物件在 XmlReader 關閉時沒有提供自動關閉連線的方法。如果客戶端傳遞了連線字串,那麼當客戶端完成對 XmlReader 的操作後,將無法關閉與 XmlReader 相關聯的連線物件。

通過參考 Data Access Application Block 程式集並匯入 Microsoft.ApplicationBlocks.Data 名稱空間,您可以輕鬆編寫使用任何一種 SqlHelper 類方法的程式碼,如下面的程式碼示例所示:

[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 [email protected] 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 [email protected] 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 類用於通過一組靜態方法來封裝資料訪問功能。該類不能被繼承或例項化,因此將其宣告為包含專用建構函式的不可繼承類。

SqlHelper 類中實現的每種方法都提供了一組一致的過載。這提供了一種很好的使用 SqlHelper 類來執行命令的模式,同時為開發人員選擇訪問資料的方式提供了必要的靈活性。每種方法的過載都支援不同的方法引數,因此開發人員可以確定傳遞連線、事務和引數資訊的方式。在 SqlHelper 類中實現的方法包括:

  • ExecuteNonQuery。此方法用於執行不返回任何行或值的命令。這些命令通常用於執行資料庫更新,但也可用於返回儲存過程的輸出引數。
  • ExecuteReader。此方法用於返回 SqlDataReader 物件,該物件包含由某一命令返回的結果集。
  • ExecuteDataset。此方法返回 DataSet 物件,該物件包含由某一命令返回的結果集。
  • 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 Beta 2.0 版本相比,該 RTM 版本包含以下新增功能和變化:

  • 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 返回包含多個表的資料集?

通過建立一個可以返回多個行集的儲存過程(通過執行多個 SELECT 語句或者對其他儲存過程進行巢狀呼叫),並使用 ExecuteDataset 方法執行該過程,您可以檢索包含多個表的資料集。

例如,假設您的資料庫包含以下儲存過程。

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 方法執行此主儲存過程將返回一個 DateSet,其中包含兩個表:一個表包含分類資料,另一個表包含產品資料。

注意: ExecuteDataset 方法不提供為返回的表指定自定義名稱的方法。第一個表的編號始終為 0,名稱為 Table,第二個表的編號為 1,名稱為 Table1,依此類推。