摘要:Data Access Application Block 是一個(gè) .NET 組件,包含優(yōu)化的數(shù)據(jù)訪問代碼,可以幫助用戶調(diào)用存儲(chǔ)過程以及向 SQL Server 數(shù)據(jù)庫(kù)發(fā)出 SQL 文本命令。它返回 SqlDataReader、DataSet 和 XmlReader 對(duì)象。您可以在自己的 .NET 應(yīng)用程序中將其作為構(gòu)造塊來(lái)使用,以減少需要?jiǎng)?chuàng)建、測(cè)試和維護(hù)的自定義代碼的數(shù)量。您可以下載完整的 C# 和 Visual Basic .NET 源代碼以及綜合文檔。
簡(jiǎn)介
您是否正在從事 .NET 應(yīng)用程序數(shù)據(jù)訪問代碼的設(shè)計(jì)和開發(fā)?您是否覺得自己總是在反復(fù)編寫相同的數(shù)據(jù)訪問代碼?您是否曾經(jīng)將數(shù)據(jù)訪問代碼包裝在 Helper 函數(shù)中,以便能夠在一行中調(diào)用存儲(chǔ)過程?如果是,那么 Microsoft® Data Access Application Block for .NET 正是為您設(shè)計(jì)的。
Data Access Application Block 將訪問 Microsoft SQL Server™ 數(shù)據(jù)庫(kù)的性能和資源管理方面的最佳經(jīng)驗(yàn)封裝在一起。您可以很方便地在自己的 .NET 應(yīng)用程序中將其作為構(gòu)造塊使用,從頁(yè)減少了需要?jiǎng)?chuàng)建、測(cè)試和維護(hù)的自定義代碼的數(shù)量。
尤其是,Data Access Application Block 可以幫助您:
- 調(diào)用存儲(chǔ)過程或 SQL 文本命令。
- 指定參數(shù)詳細(xì)信息。
- 返回 SqlDataReader、DataSet 或 XmlReader 對(duì)象。
例如,在引用了 Data Access Application Block 的應(yīng)用程序中,您可以簡(jiǎn)單地在一行代碼中調(diào)用存儲(chǔ)過程并生成 DataSet,如下所示:
1
[Visual Basic]
2
Dim ds As DataSet = SqlHelper.ExecuteDataset( _
3
connectionString, _
4
CommandType.StoredProcedure, _
5
"getProductsByCategory", _
6
new SqlParameter("@CategoryID", categoryID))
7
8
[C#]
9
DataSet ds = SqlHelper.ExecuteDataset(
10
connectionString,
11
CommandType.StoredProcedure,
12
"getProductsByCategory",
13
new SqlParameter("@CategoryID", categoryID));
注意:
Application Block for .NET(用于 .NET 的應(yīng)用程序塊)是基于對(duì)成功的 .NET 應(yīng)用程序進(jìn)行詳細(xì)研究而設(shè)計(jì)的。它以源代碼的形式提供,您可以原樣使用,也可以針對(duì)自己的應(yīng)用程序進(jìn)行自定義。該應(yīng)用程序塊并不代表未來(lái) Microsoft ADO.NET 程序庫(kù)的發(fā)展方向。Microsoft ADO.NET 程序庫(kù)是為在各種使用情況下實(shí)現(xiàn)對(duì)數(shù)據(jù)訪問行為的精確控制而建立的。將來(lái)的 ADO.NET 版本可能會(huì)使用不同的模型來(lái)實(shí)現(xiàn)這個(gè)方案
SqlHelper 類提供了一組靜態(tài)方法,可以用來(lái)向 SQL Server 數(shù)據(jù)庫(kù)發(fā)出許多各種不同類型的命令。
SqlHelperParameterCache 類提供命令參數(shù)緩存功能,可以用來(lái)提高性能。該類由許多 Execute 方法(尤其是那些只運(yùn)行存儲(chǔ)過程的重寫方法)在內(nèi)部使用。數(shù)據(jù)訪問客戶端也可以直接使用它來(lái)緩存特定命令的特定參數(shù)集。
使用 SqlHelper 類執(zhí)行命令
SqlHelper 類提供了五種 Shared (Visual Basic) 或 static (C#) 方法,它們是:ExecuteNonQuery、ExecuteDataset、ExecuteReader、ExecuteScalar 和 ExecuteXmlReader。實(shí)現(xiàn)的每種方法都提供一組一致的重載。這提供了一種很好的使用 SqlHelper 類來(lái)執(zhí)行命令的模式,同時(shí)為開發(fā)人員選擇訪問數(shù)據(jù)的方式提供了必要的靈活性。每種方法的重載都支持不同的方法參數(shù),因此開發(fā)人員可以確定傳遞連接、事務(wù)和參數(shù)信息的方式。類中實(shí)現(xiàn)的所有方法都支持以下重載:
1
[Visual Basic]
2
Execute* (ByVal connection As SqlConnection, _
3
ByVal commandType As CommandType, _
4
ByVal CommandText As String)
5
6
Execute* (ByVal connection As SqlConnection, _
7
ByVal commandType As CommandType, _
8
ByVal commandText As String, _
9
ByVal ParamArray commandParameters() As SqlParameter)
10
11
Execute* (ByVal connection As SqlConnection, _
12
ByVal spName As String, _
13
ByVal ParamArray parameterValues() As Object)
14
15
Execute* (ByVal transaction As SqlTransaction, _
16
ByVal commandType As CommandType, _
17
ByVal commandText As String)
18
19
Execute* (ByVal transaction As SqlTransaction, _
20
ByVal commandType As CommandType, _
21
ByVal commandText As String, _
22
ByVal ParamArray commandParameters() As SqlParameter)
23
24
Execute* (ByVal transaction As SqlTransaction, _
25
ByVal spName As String, _
26
ByVal ParamArray parameterValues() As Object)
27
28
[C#]
29
Execute* (SqlConnection connection, CommandType commandType,
30
string commandText)
31
32
Execute* (SqlConnection connection, CommandType commandType,
33
string commandText, params SqlParameter[] commandParameters)
34
35
Execute* (SqlConnection connection, string spName,
36
params object[] parameterValues)
37
38
Execute* (SqlConnection connection,
39
CommandType commandType, string commandText)
40
41
Execute* (SqlConnection connection,
42
CommandType commandType, string commandText,
43
params SqlParameter[] commandParameters)
44
45
Execute* (SqlConnection connection,
46
string spName, params object[] parameterValues)
47
除這些重載以外,除
ExecuteXmlReader 之外的其他方法還提供了另一種重載:允許將連接信息作為連接字符串而不是連接對(duì)象來(lái)傳遞,如下面的方法簽名所示:
[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 不支持連接字符串,因?yàn)椋号c SqlDataReader 對(duì)象不同,XmlReader 對(duì)象在 XmlReader 關(guān)閉時(shí)沒有提供自動(dòng)關(guān)閉連接的方法。如果客戶端傳遞了連接字符串,那么當(dāng)客戶端完成對(duì) XmlReader 的操作后,將無(wú)法關(guān)閉與 XmlReader 相關(guān)聯(lián)的連接對(duì)象。
通過參考 Data Access Application Block 程序集并導(dǎo)入 Microsoft.ApplicationBlocks.Data 命名空間,您可以輕松編寫使用任何一種 SqlHelper 類方法的代碼,如下面的代碼示例所示:
[Visual Basic]
Imports Microsoft.ApplicationBlocks.Data

[C#]
using Microsoft.ApplicationBlocks.Data;

導(dǎo)入命名空間后,您可以調(diào)用任何 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 類管理參數(shù)
SqlHelperParameterCache 類提供了三種可以用來(lái)管理參數(shù)的公共共享方法。它們是:
- CacheParameterSet。用于將 SqlParameters 數(shù)組存儲(chǔ)到緩存中。
- GetCachedParameterSet。用于檢索緩存的參數(shù)數(shù)組的副本。
- GetSpParameterSet。一種重載方法,用于檢索指定存儲(chǔ)過程的相應(yīng)參數(shù)(首先查詢一次數(shù)據(jù)庫(kù),然后緩存結(jié)果以便將來(lái)查詢)。
緩存和檢索參數(shù)
通過使用 CacheParameterSet 方法,可以緩存 SqlParameter 對(duì)象數(shù)組。此方法通過將連接字符串和命令文本連接起來(lái)創(chuàng)建一個(gè)鍵,然后將參數(shù)數(shù)組存儲(chǔ)在 Hashtable 中。
要從緩存中檢索參數(shù),請(qǐng)使用 GetCachedParameterSet 方法。此方法將返回一個(gè) SqlParameter 對(duì)象數(shù)組,這些對(duì)象已使用緩存(與傳遞給該方法的連接字符串和命令文本相對(duì)應(yīng))中的參數(shù)的名稱、值、方向和數(shù)據(jù)類型等進(jìn)行了初始化。
注意:
用作參數(shù)集的鍵的連接字符串通過簡(jiǎn)單的字符串比較進(jìn)行匹配。用于從 GetCachedParameterSet 中檢索參數(shù)的連接字符串必須與用來(lái)通過 CacheParameterSet 來(lái)存儲(chǔ)這些參數(shù)的連接字符串完全相同。語(yǔ)法不同的連接字符串即使語(yǔ)義相同,也不會(huì)被認(rèn)為是匹配的。
以下代碼顯示了如何使用 SqlHelperParameterCache 類來(lái)緩存和檢索 Transact-SQL 語(yǔ)句的參數(shù)。
1
[Visual Basic]
2
' 初始化連接字符串和命令文本
3
' 它們將構(gòu)成用來(lái)存儲(chǔ)和檢索參數(shù)的鍵
4
Const CONN_STRING As String = _
5
"SERVER=(local); DATABASE=Northwind; INTEGRATED SECURITY=True;"
6
Dim sql As String = _
7
"SELECT ProductName FROM Products " + _
8
"WHERE Category=@Cat AND SupplierID = @Sup"
9
10
' 緩存參數(shù)
11
Dim paramsToStore(1) As SqlParameter
12
paramsToStore(0) = New SqlParameter("@Cat", SqlDbType.Int)
13
paramsToStore(1) = New SqlParameter("@Sup", SqlDbType.Int)
14
SqlHelperParameterCache.CacheParameterSet(CONN_STRING, _
15
sql, _
16
paramsToStore)
17
18
' 從緩存中檢索參數(shù)
19
Dim storedParams(1) As SqlParameter
20
storedParams = SqlHelperParameterCache.GetCachedParameterSet( _
21
CONN_STRING, sql)
22
storedParams(0).Value = 2
23
storedParams(1).Value = 3
24
25
' 在命令中使用參數(shù)
26
Dim ds As DataSet
27
ds = SqlHelper.ExecuteDataset(CONN_STRING, _
28
CommandType.Text, _
29
sql, storedParams)
30
31
[C#]
32
// 初始化連接字符串和命令文本
33
// 它們將構(gòu)成用來(lái)存儲(chǔ)和檢索參數(shù)的鍵
34
const string CONN_STRING =
35
"SERVER=(local); DATABASE=Northwind; INTEGRATED SECURITY=True;";
36
string spName = "SELECT ProductName FROM Products " +
37
"WHERE Category=@Cat AND SupplierID = @Sup";
38
39
// 緩存參數(shù)
40
SqlParameter[] paramsToStore = new SqlParameter[2];
41
paramsToStore[0] = New SqlParameter("@Cat", SqlDbType.Int);
42
paramsToStore[1] = New SqlParameter("@Sup", SqlDbType.Int);
43
SqlHelperParameterCache.CacheParameterSet(CONN_STRING,
44
sql,
45
paramsToStore);
46
47
// 從緩存中檢索參數(shù)
48
SqlParameter storedParams = new SqlParameter[2];
49
storedParams = SqlHelperParameterCache.GetCachedParameterSet(
50
CONN_STRING, sql);
51
storedParams(0).Value = 2;
52
storedParams(1).Value = 3;
53
54
// 在命令中使用參數(shù)
55
DataSet ds;
56
ds = SqlHelper.ExecuteDataset(CONN_STRING,
57
CommandType.StoredProcedure,
58
sql, storedParams);
59
檢索存儲(chǔ)過程參數(shù)
SqlHelperParameterCache 還提供了針對(duì)特定存儲(chǔ)過程檢索參數(shù)數(shù)組的方法。一種名為 GetSpParameterSet 的重載方法提供了此功能,它包含兩種實(shí)現(xiàn)。該方法嘗試從緩存中檢索特定存儲(chǔ)過程的參數(shù)。如果這些參數(shù)尚未被緩存,則使用 .NET 的 SqlCommandBuilder 類從內(nèi)部檢索,并將它們添加到緩存中,以便用于后續(xù)的檢索請(qǐng)求。然后,為每個(gè)參數(shù)指定相應(yīng)的參數(shù)設(shè)置,最后將這些參數(shù)以數(shù)組形式返回給客戶端。以下代碼顯示了如何檢索 Northwind 數(shù)據(jù)庫(kù)中 SalesByCategory 存儲(chǔ)過程的參數(shù)。
1
[Visual Basic]
2
' 初始化連接字符串和命令文本
3
' 它們將構(gòu)成用來(lái)存儲(chǔ)和檢索參數(shù)的鍵
4
Const CONN_STRING As String = _
5
"SERVER=(local); DATABASE=Northwind; INTEGRATED SECURITY=True;"
6
Dim spName As String = "SalesByCategory"
7
8
' 檢索參數(shù)
9
Dim storedParams(1) As SqlParameter
10
storedParams = SqlHelperParameterCache.GetSpParameterSet( _
11
CONN_STRING, spName)
12
storedParams(0).Value = "Beverages"
13
storedParams(1).Value = "1997"
14
15
' 在命令中使用參數(shù)
16
Dim ds As DataSet
17
ds = SqlHelper.ExecuteDataset(CONN_STRING, _
18
CommandType.StoredProcedure, _
19
spName, storedParams)
20
21
[C#]
22
// 初始化連接字符串和命令文本
23
// 它們將構(gòu)成用來(lái)存儲(chǔ)和檢索參數(shù)的鍵
24
const string CONN_STRING =
25
"SERVER=(local); DATABASE=Northwind; INTEGRATED SECURITY=True;";
26
string spName = "SalesByCategory";
27
28
// 檢索參數(shù)
29
SqlParameter storedParams = new SqlParameter[2];
30
storedParams = SqlHelperParameterCache.GetSpParameterSet(
31
CONN_STRING, spName);
32
storedParams[0].Value = "Beverages";
33
storedParams[1].Value = "1997";
34
35
// 在命令中使用參數(shù)
36
DataSet ds;
37
ds = SqlHelper.ExecuteDataset(CONN_STRING,
38
CommandType.StoredProcedure,
39
spName, storedParams);
40
內(nèi)部設(shè)計(jì)
Data Access Application Block 包含了完整的源代碼和有關(guān)其設(shè)計(jì)的綜合指南。本節(jié)介紹有關(guān)主要實(shí)現(xiàn)的詳細(xì)信息。
SqlHelper 類實(shí)現(xiàn)詳細(xì)信息
SqlHelper 類用于通過一組靜態(tài)方法來(lái)封裝數(shù)據(jù)訪問功能。該類不能被繼承或?qū)嵗虼藢⑵渎暶鳛榘瑢S脴?gòu)造函數(shù)的不可繼承類。
在 SqlHelper 類中實(shí)現(xiàn)的每種方法都提供了一組一致的重載。這提供了一種很好的使用 SqlHelper 類來(lái)執(zhí)行命令的模式,同時(shí)為開發(fā)人員選擇訪問數(shù)據(jù)的方式提供了必要的靈活性。每種方法的重載都支持不同的方法參數(shù),因此開發(fā)人員可以確定傳遞連接、事務(wù)和參數(shù)信息的方式。在 SqlHelper 類中實(shí)現(xiàn)的方法包括:
- ExecuteNonQuery。此方法用于執(zhí)行不返回任何行或值的命令。這些命令通常用于執(zhí)行數(shù)據(jù)庫(kù)更新,但也可用于返回存儲(chǔ)過程的輸出參數(shù)。
- ExecuteReader。此方法用于返回 SqlDataReader 對(duì)象,該對(duì)象包含由某一命令返回的結(jié)果集。
- ExecuteDataset。此方法返回 DataSet 對(duì)象,該對(duì)象包含由某一命令返回的結(jié)果集。
- ExecuteScalar。此方法返回一個(gè)值。該值始終是該命令返回的第一行的第一列。
- ExecuteXmlReader。此方法返回 FOR XML 查詢的 XML 片段。
除了這些公共方法外,SqlHelper 類還包含一些專用函數(shù),用于管理參數(shù)和準(zhǔn)備要執(zhí)行的命令。不管客戶端調(diào)用什么樣的方法實(shí)現(xiàn),所有命令都通過 SqlCommand 對(duì)象來(lái)執(zhí)行。在 SqlCommand 對(duì)象能夠被執(zhí)行之前,所有參數(shù)都必須添加到 Parameters 集合中,并且必須正確設(shè)置 Connection、CommandType、CommandText 和 Transaction 屬性。SqlHelper 類中的專用函數(shù)主要用于提供一種一致的方式,以便向 SQL Server 數(shù)據(jù)庫(kù)發(fā)出命令,而不考慮客戶端應(yīng)用程序調(diào)用的重載方法實(shí)現(xiàn)。SqlHelper 類中的專用實(shí)用程序函數(shù)包括:
- AttachParameters:該函數(shù)用于將所有必要的 SqlParameter 對(duì)象連接到正在運(yùn)行的 SqlCommand。
- AssignParameterValues:該函數(shù)用于為 SqlParameter 對(duì)象賦值。
- PrepareCommand:該函數(shù)用于對(duì)命令的屬性(如連接、事務(wù)環(huán)境等)進(jìn)行初始化。
- ExecuteReader:此專用 ExecuteReader 實(shí)現(xiàn)用于通過適當(dāng)?shù)?CommandBehavior 打開 SqlDataReader 對(duì)象,以便最有效地管理與閱讀器關(guān)聯(lián)的連接的有效期。
SqlHelperParameterCache 類實(shí)現(xiàn)詳細(xì)信息
參數(shù)數(shù)組緩存在專用 Hashtable 中。從緩存中檢索的參數(shù)進(jìn)行內(nèi)部復(fù)制,這樣客戶端應(yīng)用程序能夠更改參數(shù)值以及進(jìn)行其他操作,而不會(huì)影響緩存的參數(shù)數(shù)組。專用共享函數(shù) CloneParameters 可以實(shí)現(xiàn)此目的。
常見問題
此版本包含哪些新增功能?
與 Data Access Application Block Beta 2.0 版本相比,該 RTM 版本包含以下新增功能和變化:
- SqlHelper 類方法的事務(wù)型重載不再需要 SqlConnection 參數(shù)。在此版本中,連接信息從 SqlTransaction 對(duì)象中派生,因此不必在方法簽名中包含 SqlConnection 對(duì)象參數(shù)。
- 現(xiàn)在,GetSpParameterSet 方法使用 ADO.NET CommandBuilder 類的 DeriveParameters 方法來(lái)確定存儲(chǔ)過程所需要的參數(shù)。這比 Beta 2.0 版本中直接通過查詢數(shù)據(jù)庫(kù)來(lái)檢索信息的效率更高。
可以使用 XCOPY 部署方法來(lái)部署 Data Access Application Block 程序集嗎?
可以。Microsoft.ApplicationBlocks.Data.dll 程序集在編譯后可以使用 XCOPY 進(jìn)行部署。
什么時(shí)候應(yīng)該使用 ExecuteDataset 方法,什么時(shí)候應(yīng)該使用 ExecuteReader 方法?
這個(gè)問題實(shí)際上是什么時(shí)候應(yīng)該返回 DataSet 對(duì)象中的多個(gè)數(shù)據(jù)行,什么時(shí)候應(yīng)該使用 DataReader。答案取決于您的應(yīng)用程序的特定需要,以及您在靈活性和原始性能之間的取舍。DataSet 為您提供數(shù)據(jù)的靈活的且斷開連接的關(guān)系視圖,而 DataReader 為您提供性能卓越的、只讀的、僅向前光標(biāo)。有關(guān) DataSet 和 DataReader 的全面比較,請(qǐng)參閱 Data Access Architecture Guide(英文)。
如何使用 ExecuteDataset 返回包含多個(gè)表的數(shù)據(jù)集?
通過創(chuàng)建一個(gè)可以返回多個(gè)行集的存儲(chǔ)過程(通過執(zhí)行多個(gè) SELECT 語(yǔ)句或者對(duì)其他存儲(chǔ)過程進(jìn)行嵌套調(diào)用),并使用 ExecuteDataset 方法執(zhí)行該過程,您可以檢索包含多個(gè)表的數(shù)據(jù)集。
例如,假設(shè)您的數(shù)據(jù)庫(kù)包含以下存儲(chǔ)過程。
CREATE PROCEDURE GetCategories
AS
SELECT * FROM Categories
GO
CREATE PROCEDURE GetProducts
AS
SELECT * FROM Products

您可以創(chuàng)建一個(gè)主存儲(chǔ)過程來(lái)對(duì)這些過程進(jìn)行嵌套調(diào)用,如下面的代碼示例所示。
CREATE PROCEDURE GetCategoriesAndProducts
AS
BEGIN
EXEC GetCategories
EXEC GetProducts
END

使用 ExecuteDataset 方法執(zhí)行此主存儲(chǔ)過程將返回一個(gè) DateSet,其中包含兩個(gè)表:一個(gè)表包含分類數(shù)據(jù),另一個(gè)表包含產(chǎn)品數(shù)據(jù)。
注意:
ExecuteDataset 方法不提供為返回的表指定自定義名稱的方法。第一個(gè)表的編號(hào)始終為 0,名稱為 Table,第二個(gè)表的編號(hào)為 1,名稱為 Table1,依此類推。