使用受控碼建立預存程序和使用者定義函式 (C#)
由斯科特· 米切爾
Microsoft SQL Server 2005 與 .NET Common Language Runtime 整合,以允許開發人員透過 Managed 程式代碼建立資料庫物件。 本教學課程說明如何使用 Visual Basic 或 C# 程式代碼建立受控預存程式和受控使用者定義函式。 我們也了解這些版本的 Visual Studio 如何讓您偵錯這類受控資料庫物件。
簡介
Microsoft s SQL Server 2005 等資料庫會使用 Transact-結構化查詢語言 (SQL) (T-SQL) 來插入、修改和擷取數據。 大部分的資料庫系統都包含一系列 SQL 語句的建構,這些語句接著可以當做單一可重複使用的單位來執行。 預存程式是一個範例。 另一個是 使用者定義函式(UDF),這是我們將在步驟 9 中更詳細地檢查的建構。
SQL 的核心是針對使用數據集而設計。 SELECT
、 UPDATE
和 DELETE
語句原本就適用於對應數據表中的所有記錄,而且只會受到其 WHERE
子句的限制。 然而,有許多語言功能專為一次使用一筆記錄和操作純量數據而設計。 CURSOR
允許 一組記錄一次循環執行一筆。 字串操作函式,例如 LEFT
、 CHARINDEX
和 使用 PATINDEX
純量數據。 SQL 也包含和 WHILE
等IF
控制流程語句。
Microsoft SQL Server 2005 之前,預存程式和 UDF 只能定義為 T-SQL 語句的集合。 不過,SQL Server 2005 的設計目的是要與 Common Language Runtime (CLR) 整合,這是所有 .NET 元件所使用的運行時間。 因此,您可以使用 Managed 程式代碼來建立 SQL Server 2005 資料庫中的預存程式和 UDF。 也就是說,您可以在 C# 類別中建立預存程式或 UDF 作為方法。 這可讓這些預存程式和 UDF 利用 .NET Framework 和您自己的自訂類別中的功能。
在本教學課程中,我們將檢查如何建立受控預存程式和使用者定義函式,以及如何將它們整合到 Northwind 資料庫中。 讓我們開始吧!
注意
受控資料庫物件比 SQL 對應物件提供一些優勢。 語言豐富度和熟悉度,以及重複使用現有程式代碼和邏輯的能力是主要優點。 但是,當使用不涉及太多程式邏輯的數據集時,受控資料庫物件可能會較不具效率。 如需使用Managed程式碼與T-SQL 優點的更深入討論,請參閱 使用Managed程式碼建立資料庫對象的優點。
步驟 1:將 Northwind 資料庫移出 App_Data
到目前為止,我們所有的教學課程都已使用 web 應用程式資料夾中 App_Data
Microsoft SQL Server 2005 Express Edition 資料庫檔案。 將資料庫放在 App_Data
簡化的散發中,並執行這些教學課程,因為所有檔案都位於一個目錄中,而且不需要額外的設定步驟來測試教學課程。
不過,在本教學課程中,讓我們將 Northwind 資料庫移出 App_Data
,並明確地向 SQL Server 2005 Express Edition 資料庫實例註冊。 雖然我們可以使用 資料夾中的資料庫 App_Data
來執行本教學課程的步驟,但透過明確地向SQL Server 2005 Express Edition 資料庫實例註冊資料庫,可讓許多步驟變得更簡單。
本教學課程的下載包含兩個資料庫檔案, NORTHWND.MDF
和 NORTHWND_log.LDF
- 放在名為 DataFiles
的資料夾中。 如果您遵循自己的教學課程實作,請關閉 Visual Studio,並將 和 NORTHWND_log.LDF
檔案從網站App_Data
資料夾移至NORTHWND.MDF
網站外部的資料夾。 一旦資料庫檔案移至另一個資料夾,我們需要向 SQL Server 2005 Express Edition 資料庫實例註冊 Northwind 資料庫。 這可以從 SQL Server Management Studio 完成。 如果您的計算機上已安裝非 Express Edition 的 SQL Server 2005,則您可能已安裝 Management Studio。 如果您計算機上只有 SQL Server 2005 Express Edition,請花點時間下載並安裝 Microsoft SQL Server Management Studio。
啟動 SQL Server Management Studio。 如圖 1 所示,Management Studio 一開始會詢問要連線的伺服器。 針對伺服器名稱輸入 localhost\SQLExpress,在 [驗證] 下拉式清單中選擇 [Windows 驗證],然後按兩下 [連線]。
圖 1:連線到適當的資料庫實例
聯機之後,物件總管 視窗會列出 SQL Server 2005 Express Edition 資料庫實例的相關信息,包括其資料庫、安全性資訊、管理選項等等。
我們需要將資料夾中的 DataFiles
Northwind 資料庫附加至 SQL Server 2005 Express Edition 資料庫實例(或您在何處行動資料庫)。 以滑鼠右鍵按兩下 [資料庫] 資料夾,然後從操作選單中選擇 [附加] 選項。 這會顯示 [附加資料庫] 對話框。 按兩下 [新增] 按鈕,向下切入至適當的 NORTHWND.MDF
檔案,然後按兩下 [確定]。 此時,您的畫面看起來應該類似圖 2。
圖 2:連線到適當的資料庫實例(單擊以檢視完整大小的映射)
注意
透過 Management Studio 連接到 SQL Server 2005 Express Edition 實例時,[附加資料庫] 對話框不允許您向下切入使用者配置檔目錄,例如[我的檔]。 因此,請務必將 NORTHWND.MDF
和 NORTHWND_log.LDF
檔案放在非使用者配置檔目錄中。
按兩下 [確定] 按鈕以附加資料庫。 [附加資料庫] 對話框將會關閉,而 物件總管 現在應該會列出剛附加的資料庫。 Northwind 資料庫的名稱可能類似 9FE54661B32FDD967F51D71D0D5145CC_LINE ARTICLES\DATATUTORIALS\VOLUME 3\CSHARP\73\ASPNET_DATA_TUTORIAL_75_CS\APP_DATA\NORTHWND.MDF
。 以滑鼠右鍵按兩下資料庫並選擇 [重新命名],將資料庫重新命名為 Northwind。
圖 3:將資料庫重新命名為 Northwind
步驟 2:在 Visual Studio 中建立新的方案和 SQL Server 專案
若要在 SQL Server 2005 中建立 Managed 預存程式或 UDF,我們將在類別中撰寫預存程式和 UDF 邏輯作為 C# 程式代碼。 撰寫程式代碼之後,我們必須將此類別編譯成元件( .dll
檔案)、向 SQL Server 資料庫註冊元件,然後在資料庫中建立預存程式或 UDF 物件,指向元件中對應的方法。 這些步驟全都可以手動執行。 我們可以在任何文本編輯器中建立程式代碼、使用 C# 編譯程式從命令行編譯程式 (csc.exe
)、使用 CREATE ASSEMBLY
命令或 Management Studio 向資料庫註冊程式代碼,然後透過類似的方式新增預存程式或 UDF 物件。 幸運的是,Visual Studio 的 Professional 和 Team Systems 版本包含可自動執行這些工作的 SQL Server 項目類型。 在本教學課程中,我們將逐步解說如何使用 SQL Server 項目類型來建立受控預存程式和 UDF。
注意
如果您使用 Visual Web Developer 或 Standard 版的 Visual Studio,則必須改用手動方法。 步驟 13 提供手動執行這些步驟的詳細指示。 建議您先閱讀步驟 2 到 12,再閱讀步驟 13,因為這些步驟包含必須套用的重要 SQL Server 組態指示,不論您使用的 Visual Studio 版本為何。
從開啟 Visual Studio 開始。 從 [檔案] 功能表中,選擇 [新增專案] 以顯示 [新增專案] 對話框(請參閱圖 4)。 向下切入至 [資料庫] 項目類型,然後從右側所列的 [範本] 中選擇建立新的 SQL Server 專案。 我已選擇將此專案 ManagedDatabaseConstructs
命名為 ,並將它放在名為 Tutorial75
的方案內。
圖 4:建立新的 SQL Server 專案(按兩下以檢視完整大小的映像)
按兩下 [新增專案] 對話框中的 [確定] 按鈕,以建立 [方案] 和 [SQL Server 專案]。
SQL Server 專案會系結至特定資料庫。 因此,在建立新的 SQL Server 專案之後,我們立即被要求指定這項資訊。 圖 5 顯示 [新增資料庫參考] 對話框,該對話框已填妥,以指向我們在步驟 1 中 SQL Server 2005 Express Edition 資料庫實例中註冊的 Northwind 資料庫。
圖 5:將 SQL Server 專案與 Northwind 資料庫產生關聯
為了偵錯我們將在此專案中建立的 Managed 預存程式和 UDF,我們需要啟用連線的 SQL/CLR 偵錯支援。 每當將 SQL Server 專案與新的資料庫產生關聯時(如圖 5 所示),Visual Studio 會詢問我們是否要在連線上啟用 SQL/CLR 偵錯(請參閱圖 6)。 按一下是。
圖 6:啟用 SQL/CLR 偵錯
此時,新的 SQL Server 專案已新增至方案。 它包含名為 Test Scripts
的資料夾,其中包含名為 Test.sql
的檔案,用於偵錯專案中建立的Managed資料庫物件。 我們將在步驟 12 中查看偵錯。
我們現在可以將新的 Managed 預存程式和 UDF 新增至此專案,但在我們這麼做之前,讓我們先將現有的 Web 應用程式包含在解決方案中。 從 [檔案] 功能選取 [新增] 選項,然後選擇 [現有網站]。 流覽至適當的網站資料夾,然後按兩下 [確定]。 如圖 7 所示,這會更新方案以包含兩個專案:網站和 ManagedDatabaseConstructs
SQL Server 專案。
圖 7:方案總管 現在包含兩個專案
NORTHWNDConnectionString
中的Web.config
值目前會參考 NORTHWND.MDF
資料夾中的App_Data
檔案。 由於我們已從 App_Data
中移除此資料庫,並在 SQL Server 2005 Express Edition 資料庫實例中明確註冊它,因此我們需要對應地更新 NORTHWNDConnectionString
值。 Web.config
在網站中開啟檔案並變更NORTHWNDConnectionString
值,讓 連接字串 讀取:Data Source=localhost\SQLExpress;Initial Catalog=Northwind;Integrated Security=True
。 在此變更之後,中的 區 <connectionStrings>
段 Web.config
看起來應該類似下列:
<connectionStrings>
<add name="NORTHWNDConnectionString" connectionString=
"Data Source=localhost\SQLExpress;Initial Catalog=Northwind;
Integrated Security=True;Pooling=false"
providerName="System.Data.SqlClient" />
</connectionStrings>
注意
如上一個教學課程所述,從用戶端應用程式偵錯 SQL Server 物件時,例如 ASP.NET 網站,我們需要停用連線共用。 此 連接字串 會停用連線共用 ( Pooling=false
。 如果您不打算從 ASP.NET 網站偵錯 Managed 預存程式和 UDF,請啟用連線共用。
步驟 3:建立受控預存程式
若要將Managed預存程式新增至 Northwind 資料庫,我們必須先將預存程式建立為 SQL Server 專案中的方法。 從 方案總管,以滑鼠右鍵按下ManagedDatabaseConstructs
專案名稱,然後選擇新增專案。 這會顯示 [新增專案] 對話框,其中會列出可加入至專案的Managed資料庫物件類型。 如圖 8 所示,這包括預存程式和使用者定義函數等。
讓我們從新增預存程式開始,這個預存程式只會傳回已中止的所有產品。 將新的預存程式檔 GetDiscontinuedProducts.cs
命名為 。
圖 8:新增名為 GetDiscontinuedProducts.cs
的新預存程式(按一下以檢視完整大小的影像)
這會使用下列內容建立新的 C# 類別檔案:
using System;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;
public partial class StoredProcedures
{
[Microsoft.SqlServer.Server.SqlProcedure]
public static void GetDiscontinuedProducts()
{
// Put your code here
}
};
請注意,預存程式會實作為static
名為 StoredProcedures
類別partial
檔案內的方法。 此外,方法 GetDiscontinuedProducts
會以 SqlProcedure attribute
裝飾 ,它會將 方法標示為預存程式。
下列程式代碼會SqlCommand
建立 物件,並將其設定CommandText
為SELECT
查詢,此查詢會針對欄位等於 1 的產品Discontinued
,從數據表傳回所有數據Products
行。 然後它會執行 命令,並將結果傳回用戶端應用程式。 將此程式碼新增到 GetDiscontinuedProducts
方法。
// Create the command
SqlCommand myCommand = new SqlCommand();
myCommand.CommandText =
@"SELECT ProductID, ProductName, SupplierID, CategoryID,
QuantityPerUnit, UnitPrice, UnitsInStock, UnitsOnOrder,
ReorderLevel, Discontinued
FROM Products
WHERE Discontinued = 1";
// Execute the command and send back the results
SqlContext.Pipe.ExecuteAndSend(myCommand);
所有 Managed 資料庫物件都可以存取SqlContext
代表呼叫端內容的物件。 SqlContext
透過物件的 Pipe
屬性,提供物件的存取SqlPipe
權。 這個 SqlPipe
對像是用來在 SQL Server 資料庫與呼叫端應用程式之間傳送資訊。 正如其名稱所暗示, ExecuteAndSend
方法 會執行傳入 SqlCommand
的物件,並將結果傳回用戶端應用程式。
注意
Managed 資料庫物件最適合使用程式邏輯而非以集合為基礎的邏輯的預存程式和 UDF。 程序邏輯牽涉到逐列處理數據集,或使用純量數據。 GetDiscontinuedProducts
不過,我們剛才建立的方法並不涉及任何程序性邏輯。 因此,最好將其實作為 T-SQL 預存程式。 它會實作為受控預存程式,以示範建立和部署受控預存程式所需的步驟。
步驟 4:部署受控預存程式
完成此程式代碼之後,我們即可將其部署至 Northwind 資料庫。 部署 SQL Server 專案會將程式代碼編譯成元件、向資料庫註冊元件,並在資料庫中建立對應的物件,將它們連結至元件中的適當方法。 [部署] 選項所執行的工作集在步驟 13 中更精確。 以滑鼠右鍵按兩下 ManagedDatabaseConstructs
方案總管中的項目名稱,然後選擇 [部署] 選項。 不過,部署失敗,並出現下列錯誤:『EXTERNAL』 附近的語法不正確。 您可能要將目前資料庫的相容性層級設成高一點的值,以啟用這項功能。 請參閱預存程式 sp_dbcmptlevel
的說明。
嘗試向 Northwind 資料庫註冊元件時,就會發生此錯誤訊息。 若要向 SQL Server 2005 資料庫註冊元件,資料庫相容性層級必須設定為 90。 根據預設,新的 SQL Server 2005 資料庫具有 90 的相容性層級。 不過,使用 Microsoft SQL Server 2000 建立的資料庫的預設相容性層級為 80。 由於 Northwind 資料庫最初是 SQL Server 2000 資料庫Microsoft,因此其相容性層級目前設定為 80,因此必須增加到 90,才能註冊受控資料庫物件。
若要更新資料庫的相容性層級,請在Management Studio 中開啟 [新增查詢] 視窗,然後輸入:
exec sp_dbcmptlevel 'Northwind', 90
按兩下工具列中的[執行] 圖示,以執行上述查詢。
圖 9:更新 Northwind 資料庫的相容性層級 (按兩下以檢視完整大小的映射)
更新相容性層級之後,請重新部署 SQL Server 專案。 這次部署應該完成而不會發生錯誤。
返回 SQL Server Management Studio,以滑鼠右鍵按兩下 物件總管 中的 Northwind 資料庫,然後選擇 [重新整理]。 接下來,向下切入至 [可程式性] 資料夾,然後展開 [元件] 資料夾。 如圖 10 所示,Northwind 資料庫現在包含專案所產生的 ManagedDatabaseConstructs
元件。
圖 10:元件 ManagedDatabaseConstructs
現在已向 Northwind 資料庫註冊
同時展開 [預存程式] 資料夾。 您會在那裡看到名為 GetDiscontinuedProducts
的預存程式。 此預存程式是由部署程式所建立,並指向 GetDiscontinuedProducts
元件中的 ManagedDatabaseConstructs
方法。 GetDiscontinuedProducts
當預存程式執行時,它會接著執行 GetDiscontinuedProducts
方法。 因為這是受控預存程式,因此無法透過 Management Studio 進行編輯(因此預存程式名稱旁的鎖定圖示)。
圖 11:預 GetDiscontinuedProducts
存程式列在預存程式資料夾中
我們還需要克服一個障礙,才能呼叫 Managed 預存程式:資料庫已設定為防止執行 Managed 程式代碼。 開啟新的查詢視窗並執行預存程式來 GetDiscontinuedProducts
確認這一點。 您會收到下列錯誤訊息:停用 .NET Framework 中的使用者程式代碼執行。 啟用 'clr enabled configuration option。
若要檢查 Northwind 資料庫的組態資訊,請在查詢視窗中輸入並執行 命令 exec sp_configure
。 這會顯示已啟用 clr 的設定目前設定為 0。
圖 12:已啟用 clr 的設定目前設定為 0(按兩下以檢視完整大小的影像)
請注意,圖 12 中的每個組態設定都會列出四個值:最小值和最大值,以及組態和執行值。 若要更新已啟用 clr 設定的組態值,請執行下列命令:
exec sp_configure 'clr enabled', 1
如果您重新執行 , exec sp_configure
您會看到上述語句已將啟用 clr 的設定值更新為 1,但執行值仍設定為 0。 若要讓此組態變更生效,我們需要執行 RECONFIGURE
命令,這會將回合值設定為目前的組態值。 只要在查詢視窗中輸入 RECONFIGURE
,然後按下工具列中的 [執行] 圖示。 如果您現在執行 exec sp_configure
,您應該會看到已啟用 clr 設定的組態和執行值的值 1。
完成 clr 設定之後,我們即可執行受控 GetDiscontinuedProducts
預存程式。 在查詢視窗中,輸入並執行 命令 exec
GetDiscontinuedProducts
。 叫用預存程式會導致 方法中的 GetDiscontinuedProducts
對應 Managed 程式代碼執行。 此程式代碼會發出 SELECT
查詢,以傳回已停止的所有產品,並將此數據傳回給呼叫的應用程式,也就是此實例中的 SQL Server Management Studio。 Management Studio 會收到這些結果,並在 [結果] 視窗中顯示這些結果。
圖 13:預 GetDiscontinuedProducts
存程式會傳回所有已停止的產品(按兩下以檢視完整大小的影像)
步驟 5:建立接受輸入參數的 Managed 預存程式
我們在這些教學課程中建立的許多查詢和預存程式都使用了 參數。 例如,在為具型別數據集 s TableAdapters 建立新的預存程式教學課程中,我們建立了名為 GetProductsByCategoryID
的預存程式,該預存程式接受名為 的@CategoryID
輸入參數。 然後,預存程式會傳回符合所提供@CategoryID
參數值的所有產品CategoryID
。
若要建立接受輸入參數的 Managed 預存程式,只需在方法定義中指定這些參數即可。 為了說明這一點,讓我們將另一個 Managed 預存程式新增至 ManagedDatabaseConstructs
名為 GetProductsWithPriceLessThan
的專案。 此 Managed 預存程式會接受指定價格的輸入參數,並傳回欄位小於參數值的所有產品 UnitPrice
。
若要將新的預存程式新增至專案,請以滑鼠右鍵按兩下 ManagedDatabaseConstructs
專案名稱,然後選擇加入新的預存程式。 將檔案命名為 GetProductsWithPriceLessThan.cs
。 如我們在步驟 3 中所見,這會建立新的 C# 類別檔案,並將名為 GetProductsWithPriceLessThan
的方法放在 類別 StoredProcedures
內partial
。
GetProductsWithPriceLessThan
更新 方法的定義,讓它接受SqlMoney
名為 price
的輸入參數,並撰寫程式代碼來執行並傳回查詢結果:
[Microsoft.SqlServer.Server.SqlProcedure]
public static void GetProductsWithPriceLessThan(SqlMoney price)
{
// Create the command
SqlCommand myCommand = new SqlCommand();
myCommand.CommandText =
@"SELECT ProductID, ProductName, SupplierID, CategoryID,
QuantityPerUnit, UnitPrice, UnitsInStock, UnitsOnOrder,
ReorderLevel, Discontinued
FROM Products
WHERE UnitPrice < @MaxPrice";
myCommand.Parameters.AddWithValue("@MaxPrice", price);
// Execute the command and send back the results
SqlContext.Pipe.ExecuteAndSend(myCommand);
}
方法 GetProductsWithPriceLessThan
的定義和程式代碼與步驟 3 中建立之方法的定義和程式代碼 GetDiscontinuedProducts
非常類似。 唯一的差異在於GetProductsWithPriceLessThan
方法接受做為輸入參數 ()、s 查詢包含參數 (price
@MaxPrice
),SqlCommand
而且參數會新增至 SqlCommand
s Parameters
集合,並指派變數的值price
。
新增此程式代碼之後,請重新部署 SQL Server 專案。 接下來,返回 SQL Server Management Studio 並重新整理預存程序資料夾。 您應該會看到新的項目 GetProductsWithPriceLessThan
從查詢視窗中,輸入並執行 命令 exec GetProductsWithPriceLessThan 25
,此命令會列出小於 $25 的所有產品,如圖 14 所示。
圖 14:顯示 $25 以下的產品(按兩下以檢視全尺寸影像)
步驟 6:從數據存取層呼叫受控預存程式
此時,我們已將 和 GetProductsWithPriceLessThan
Managed 預存程式新增GetDiscontinuedProducts
至專案,ManagedDatabaseConstructs
並已向 Northwind SQL Server 資料庫註冊它們。 我們也從 SQL Server Management Studio 叫用這些受控預存程式(請參閱圖 13 和 14)。 不過,為了讓 ASP.NET 應用程式使用這些受控預存程式,我們需要將它們新增至架構中的數據存取和商業規則層。 在此步驟中,我們會在 Typed DataSet 中NorthwindWithSprocs
新增兩個新方法ProductsTableAdapter
,其最初是在建立具型別數據集 s TableAdapters 的預存程式教學課程中建立的。 在步驟 7 中,我們會將對應的方法新增至 BLL。
NorthwindWithSprocs
在 Visual Studio 中開啟具型別數據集,首先將新方法加入至具名 GetDiscontinuedProducts
的 ProductsTableAdapter
。 若要將新方法新增至 TableAdapter,請以滑鼠右鍵按兩下設計工具中的 TableAdapter 名稱,然後從操作功能表中選擇 [新增查詢] 選項。
注意
由於我們已將 Northwind 資料庫從 App_Data
資料夾移至 SQL Server 2005 Express Edition 資料庫實例,因此必須更新 Web.config 中對應的 連接字串,以反映這項變更。 在步驟 2 中,我們已討論更新 NORTHWNDConnectionString
中的 Web.config
值。 如果您忘記進行此更新,您會看到錯誤訊息無法新增查詢。 嘗試將新方法新增至 TableAdapter 時,在對話框中找不到對象的Web.config
連接NORTHWNDConnectionString
。 若要解決此錯誤,請按兩下 [確定],然後移至 並 Web.config
更新 NORTHWNDConnectionString
步驟 2 中所述的值。 然後嘗試將方法重新新增至 TableAdapter。 這次應該會正常運作,而不會發生錯誤。
新增方法會啟動 TableAdapter 查詢組態精靈,我們過去教學課程中曾多次使用此精靈。 第一個步驟要求我們指定 TableAdapter 應該如何存取資料庫:透過臨機操作 SQL 語句,或透過新的或現有的預存程式。 由於我們已經使用資料庫建立並註冊 GetDiscontinuedProducts
受控預存程式,請選擇 [使用現有的預存程式] 選項,然後按 [下一步]。
圖 15:選擇 [使用現有的預存程序選項] (按兩下以檢視完整大小的影像)
下一個畫面會提示我們輸入 方法將叫用的預存程式。 GetDiscontinuedProducts
從下拉式清單中選擇受控預存程式,然後按 [下一步]。
圖 16:選取 GetDiscontinuedProducts
受控預存程式 (按一下以檢視完整大小的映像)
然後,系統會要求我們指定預存程式是否傳回數據列、單一值或無任何值。 由於 GetDiscontinuedProducts
會傳回已停止的產品數據列集,請選擇第一個選項(表格式數據),然後按 [下一步]。
圖 17:選取表格式資料選項 (按一下以檢視完整大小的影像)
最後一個精靈畫面可讓我們指定所使用的數據存取模式,以及所產生方法的名稱。 將兩個複選框都保留為複選框,並將方法 FillByDiscontinued
命名為 和 GetDiscontinuedProducts
。 按一下 [完成] 以完成程序。
圖 18:將方法FillByDiscontinued
命名為 ,然後按兩下GetDiscontinuedProducts
以檢視完整大小的影像)
重複這些步驟,為Managed預存程式建立名為 FillByPriceLessThan
和 ProductsTableAdapter
GetProductsWithPriceLessThan
GetProductsWithPriceLessThan
的方法。
圖 19 顯示 DataSet 設計工具在將 方法新增至 ProductsTableAdapter
和 GetProductsWithPriceLessThan
Managed 預存程式的 之後的GetDiscontinuedProducts
螢幕快照。
圖 19:包含 ProductsTableAdapter
此步驟中新增的新方法 (按兩下以檢視完整大小的影像)
步驟 7:將對應的方法新增至商業規則層
既然我們已更新數據存取層,以包含呼叫步驟 4 和 5 中新增之 Managed 預存程式的方法,我們需要將對應的方法新增至商業規則層。 將下列兩種方法新增至 ProductsBLLWithSprocs
類別:
[System.ComponentModel.DataObjectMethodAttribute
(System.ComponentModel.DataObjectMethodType.Select, false)]
public NorthwindWithSprocs.ProductsDataTable GetDiscontinuedProducts()
{
return Adapter.GetDiscontinuedProducts();
}
[System.ComponentModel.DataObjectMethodAttribute
(System.ComponentModel.DataObjectMethodType.Select, false)]
public NorthwindWithSprocs.ProductsDataTable
GetProductsWithPriceLessThan(decimal priceLessThan)
{
return Adapter.GetProductsWithPriceLessThan(priceLessThan);
}
這兩種方法只會呼叫對應的 DAL 方法,並傳 ProductsDataTable
回 實例。 DataObjectMethodAttribute
上述每個方法的標記會導致這些方法包含在 ObjectDataSource 設定數據源精靈之 SELECT 索引標籤標的下拉式清單中。
步驟 8:從表示層叫用 Managed 預存程式
透過增強商業規則和數據存取層,以包含呼叫 GetDiscontinuedProducts
和 GetProductsWithPriceLessThan
Managed 預存程式的支持,我們現在可以透過 ASP.NET 頁面顯示這些預存程序結果。
ManagedFunctionsAndSprocs.aspx
開啟資料夾中的頁面AdvancedDAL
,然後從 [工具箱] 將 GridView 拖曳至設計工具。 將 GridView 的 ID
屬性設定為 DiscontinuedProducts
,並從其智慧標記將它系結至名為 DiscontinuedProductsDataSource
的新 ObjectDataSource。 將 ObjectDataSource 設定為從 ProductsBLLWithSprocs
類別 s GetDiscontinuedProducts
方法提取其數據。
圖 20:將 ObjectDataSource 設定為使用 ProductsBLLWithSprocs
類別 (按一下以檢視完整大小的影像)
圖 21:從 [選取] 索引標籤的下拉式清單中選擇 GetDiscontinuedProducts
[方法] (按兩下以檢視完整大小的影像)
由於此方格將用來只顯示產品資訊,請將 UPDATE、INSERT 和 DELETE 索引標籤中的下拉式清單設定為 [無],然後按兩下 [完成]。
完成精靈之後,Visual Studio 會自動為 中的每個 ProductsDataTable
數據欄位新增 BoundField 或 CheckBoxField。 請花點時間移除 和 Discontinued
以外的ProductName
所有字段,此時您的 GridView 和 ObjectDataSource 宣告式標記看起來應該類似下列:
<asp:GridView ID="DiscontinuedProducts" runat="server"
AutoGenerateColumns="False" DataKeyNames="ProductID"
DataSourceID="DiscontinuedProductsDataSource">
<Columns>
<asp:BoundField DataField="ProductName" HeaderText="ProductName"
SortExpression="ProductName" />
<asp:CheckBoxField DataField="Discontinued"
HeaderText="Discontinued"
SortExpression="Discontinued" />
</Columns>
</asp:GridView>
<asp:ObjectDataSource ID="DiscontinuedProductsDataSource" runat="server"
OldValuesParameterFormatString="original_{0}"
SelectMethod="GetDiscontinuedProducts" TypeName="ProductsBLLWithSprocs">
</asp:ObjectDataSource>
請花點時間透過瀏覽器檢視此頁面。 瀏覽頁面時,ObjectDataSource 會呼叫 ProductsBLLWithSprocs
類別 s GetDiscontinuedProducts
方法。 如我們在步驟 7 中所見,此方法會向下呼叫 DAL 類別 s ProductsDataTable
GetDiscontinuedProducts
方法,以叫 GetDiscontinuedProducts
用預存程式。 此預存程式是受控預存程式,會執行我們在步驟 3 中建立的程式代碼,並傳回已停止的產品。
Managed 預存程式傳回的結果會由 DAL 封裝成 ProductsDataTable
,然後傳回至 BLL,然後將結果傳回至表示層,並系結至 GridView 並顯示。 如預期般,方格會列出已停止的產品。
圖 22:已停止的產品已列出(按兩下以檢視完整大小的影像)
如需進一步的做法,請將 TextBox 和另一個 GridView 新增至頁面。 呼叫 類別 s GetProductsWithPriceLessThan
方法,讓此 GridView 顯示小於輸入 TextBox ProductsBLLWithSprocs
數量的產品。
步驟 9:建立和呼叫 T-SQL UDF
使用者定義函式或 UDF 是資料庫物件,在程式設計語言中密切模擬函式的語意。 就像 C# 中的函式一樣,UDF 可以包含一個可變數目的輸入參數,並傳回特定類型的值。 UDF 可以傳回純量資料 - 字串、 整數等等 - 或表格式數據。 讓我們快速查看這兩種類型的UDF,從傳回純量數據類型的UDF開始。
下列 UDF 會計算特定產品的庫存估計值。 它會採用三個輸入參數 -- 特定 UnitPrice
產品的、 UnitsInStock
和 Discontinued
值 ,並傳回 類型的 money
值。 它會將乘UnitPrice
UnitsInStock
以 計算清查的估計值。 對於已中止的專案,此值會減半。
CREATE FUNCTION udf_ComputeInventoryValue
(
@UnitPrice money,
@UnitsInStock smallint,
@Discontinued bit
)
RETURNS money
AS
BEGIN
DECLARE @Value decimal
SET @Value = ISNULL(@UnitPrice, 0) * ISNULL(@UnitsInStock, 0)
IF @Discontinued = 1
SET @Value = @Value * 0.5
RETURN @Value
END
將這個 UDF 新增至資料庫之後,即可透過 Management Studio 來找到它,方法是展開 [可程式性] 資料夾、[Functions] 和 [純量值函式]。 它可用於查詢中 SELECT
,如下所示:
SELECT ProductID, ProductName, dbo.udf_ComputeInventoryValue
(UnitPrice, UnitsInStock, Discontinued) as InventoryValue
FROM Products
ORDER BY InventoryValue DESC
我已將 udf_ComputeInventoryValue
UDF 新增至 Northwind 資料庫;圖 23 顯示透過 Management Studio 檢視時上述 SELECT
查詢的輸出。 另請注意,UDF 會列在 物件總管 的 Scalar-value Functions 資料夾底下。
圖 23:列出每個產品的庫存值 (按兩下以檢視完整大小的影像)
UDF 也可以傳回表格式數據。 例如,我們可以建立 UDF 來傳回屬於特定類別的產品:
CREATE FUNCTION dbo.udf_GetProductsByCategoryID
(
@CategoryID int
)
RETURNS TABLE
AS
RETURN
(
SELECT ProductID, ProductName, SupplierID, CategoryID,
QuantityPerUnit, UnitPrice, UnitsInStock, UnitsOnOrder,
ReorderLevel, Discontinued
FROM Products
WHERE CategoryID = @CategoryID
)
udf_GetProductsByCategoryID
UDF 接受@CategoryID
輸入參數,並傳回指定SELECT
查詢的結果。 建立之後,可以在查詢的 FROM
SELECT
(或 JOIN
) 子句中參考此 UDF。 下列範例會傳回 ProductID
每個飲料的、 ProductName
和 CategoryID
值。
SELECT ProductID, ProductName, CategoryID
FROM dbo.udf_GetProductsByCategoryID(1)
我已將 udf_GetProductsByCategoryID
UDF 新增至 Northwind 資料庫;圖 24 顯示透過 Management Studio 檢視時上述 SELECT
查詢的輸出。 傳回表格式數據的 UDF 可以在 物件總管 資料表值 Functions 資料夾中找到。
圖 24:每個飲料的 、 ProductName
和 CategoryID
都列出 (按兩下以檢視完整大小的影像)ProductID
步驟 10:建立受控 UDF
udf_ComputeInventoryValue
在上述範例中建立的 和 udf_GetProductsByCategoryID
UDF 是 T-SQL 資料庫物件。 SQL Server 2005 也支援受控 UDF,其可新增至 ManagedDatabaseConstructs
專案,就像步驟 3 和 5 中的 Managed 預存程式一樣。 在此步驟中,讓我們在 Managed 程式代碼中實 udf_ComputeInventoryValue
作 UDF。
若要將受控 UDF 新增至ManagedDatabaseConstructs
專案,請以滑鼠右鍵按兩下 方案總管 中的項目名稱,然後選擇 [新增專案]。 從[新增專案] 對話框中選取 [使用者定義範本],並將新的 UDF 檔案 udf_ComputeInventoryValue_Managed.cs
命名為 。
圖 25:將新的受控 UDF 新增至 ManagedDatabaseConstructs
專案 (按兩下以檢視完整大小的影像)
用戶定義函式範本會建立名為 partial
UserDefinedFunctions
的類別,其名稱與類別檔名相同的方法(udf_ComputeInventoryValue_Managed
在此實例中為 )。 這個方法是使用 SqlFunction
屬性裝飾的,此屬性會將方法標示為Managed UDF。
using System;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;
public partial class UserDefinedFunctions
{
[Microsoft.SqlServer.Server.SqlFunction]
public static SqlString udf_ComputeInventoryValue_Managed()
{
// Put your code here
return new SqlString("Hello");
}
};
方法 udf_ComputeInventoryValue
目前會傳 SqlString
回 物件 ,且不接受任何輸入參數。 我們需要更新方法定義,讓它接受三個SqlMoney
輸入參數 - UnitPrice
、 UnitsInStock
和 Discontinued
- 並傳回 物件。 計算清查值的邏輯與 T-SQL udf_ComputeInventoryValue
UDF 中的相同。
[Microsoft.SqlServer.Server.SqlFunction]
public static SqlMoney udf_ComputeInventoryValue_Managed
(SqlMoney UnitPrice, SqlInt16 UnitsInStock, SqlBoolean Discontinued)
{
SqlMoney inventoryValue = 0;
if (!UnitPrice.IsNull && !UnitsInStock.IsNull)
{
inventoryValue = UnitPrice * UnitsInStock;
if (Discontinued == true)
inventoryValue = inventoryValue * new SqlMoney(0.5);
}
return inventoryValue;
}
請注意,UDF 方法的輸入參數是其對應的 SQL 類型:SqlMoney
針對 UnitPrice
欄位、SqlInt16
針對 UnitsInStock
和 SqlBoolean
。Discontinued
這些數據類型會反映數據表中 Products
定義的類型:數據 UnitPrice
行的類型為 類型 money
、 UnitsInStock
類型 smallint
的數據行,以及 Discontinued
類型的數據 bit
行。
程式代碼一開始會建立 SqlMoney
名為 inventoryValue
的實例,並將值指派為0。 數據表Products
允許 和 UnitsInStock
數據列中的UnitsInPrice
資料庫NULL
值。 因此,我們需要先檢查這些值是否包含 NULL
s,我們透過 SqlMoney
物件 s IsNull
屬性執行此動作。 如果 和 UnitsInStock
都包含UnitPrice
非NULL
值,則我們會將 計算inventoryValue
為兩者的乘積。 然後,如果 Discontinued
為 true,則我們會減半值。
注意
物件 SqlMoney
只允許將兩 SqlMoney
個實例相乘。 它不允許 SqlMoney
實例乘以常值浮點數。 因此,若要將 inventoryValue
它乘以值為0.5的新 SqlMoney
實例。
步驟 11:部署受控 UDF
既然已建立受控 UDF,我們已經準備好將其部署至 Northwind 資料庫。 如我們在步驟 4 中所見,SQL Server 專案中的 Managed 物件會以滑鼠右鍵單擊 方案總管 中的項目名稱,並從操作功能表中選擇 [部署] 選項來部署。
部署項目之後,請返回 SQL Server Management Studio 並重新整理 Scalar 值 Functions 資料夾。 您現在應該會看到兩個專案:
dbo.udf_ComputeInventoryValue
- 在步驟 9 中建立的 T-SQL UDF,以及dbo.udf ComputeInventoryValue_Managed
- 在剛部署的步驟 10 中建立的受控 UDF。
若要測試此受控 UDF,請從 Management Studio 內執行下列查詢:
SELECT ProductID, ProductName,
dbo.udf_ComputeInventoryValue_Managed(
UnitPrice,
UnitsInStock,
Discontinued
) as InventoryValue
FROM Products
ORDER BY InventoryValue DESC
此命令會使用受控 udf ComputeInventoryValue_Managed
UDF,而不是 T-SQL udf_ComputeInventoryValue
UDF,但輸出相同。 請參閱圖 23 以查看 UDF 輸出的螢幕快照。
步驟 12:偵錯 Managed 資料庫物件
在偵 錯預存程式 教學課程中,我們討論了透過Visual Studio對 SQL Server 進行偵錯的三個選項:從 SQL Server 專案進行直接資料庫偵錯、應用程式偵錯和偵錯。 Managed 資料庫對象無法透過直接資料庫偵錯進行偵錯,但可以從用戶端應用程式和直接從 SQL Server 專案進行偵錯。 不過,為了讓偵錯能夠運作,SQL Server 2005 資料庫必須允許 SQL/CLR 偵錯。 回想一下,當我們第一次建立 ManagedDatabaseConstructs
專案時,Visual Studio 會詢問我們是否要啟用 SQL/CLR 偵錯(請參閱步驟 2 中的圖 6)。 從 [伺服器總管] 視窗以滑鼠右鍵按兩下資料庫,即可修改此設定。
圖 26:確定資料庫允許 SQL/CLR 偵錯
假設我們想要偵錯 GetProductsWithPriceLessThan
Managed 預存程式。 我們會從在方法的程式 GetProductsWithPriceLessThan
代碼中設定斷點開始。
圖 27:在 GetProductsWithPriceLessThan
方法中設定斷點 (按兩下以檢視完整大小的影像)
讓我們先看看從 SQL Server Project 偵錯 Managed 資料庫物件。 因為我們的解決方案包含兩個專案 -- ManagedDatabaseConstructs
SQL Server 專案和我們的網站 - 為了從 SQL Server 專案進行偵錯,我們需要指示 Visual Studio 在開始偵錯時啟動 ManagedDatabaseConstructs
SQL Server 專案。 以滑鼠右鍵按下 ManagedDatabaseConstructs
方案總管 中的項目,然後從操作選單中選擇 [設定為啟始專案] 選項。
ManagedDatabaseConstructs
從調試程式啟動專案時,它會在位於 Test Scripts
資料夾中的Test.sql
檔案中執行 SQL 語句。 例如,若要測試 GetProductsWithPriceLessThan
Managed 預存程式,請將現有的 Test.sql
檔案內容取代為下列語句,以叫 GetProductsWithPriceLessThan
用傳入 @CategoryID
14.95 值的 Managed 預存程式:
exec GetProductsWithPriceLessThan 14.95
一旦您將上述腳本輸入 , Test.sql
請移至 [偵錯] 功能表並選擇 [開始偵錯],或按 F5 或工具列中的綠色播放圖示,開始偵錯。 這會建置方案內的專案、將 Managed 資料庫物件部署到 Northwind 資料庫,然後執行 Test.sql
腳本。 此時會叫用斷點,我們可以逐步執行 GetProductsWithPriceLessThan
方法、檢查輸入參數的值等等。
圖 28:叫用方法中的 GetProductsWithPriceLessThan
斷點 (按兩下以檢視完整大小的影像)
為了讓 SQL 資料庫物件透過用戶端應用程式進行偵錯,資料庫必須設定為支援應用程式偵錯。 以滑鼠右鍵按兩下 [伺服器總管] 中的資料庫,並確定已核取 [應用程式偵錯] 選項。 此外,我們需要設定 ASP.NET 應用程式來與 SQL 調試程式整合,以及停用連線共用。 這些步驟已在偵錯預存程式教學課程的步驟 2 中詳細討論。
設定 ASP.NET 應用程式和資料庫之後,請將 ASP.NET 網站設定為啟始專案並開始偵錯。 如果您瀏覽的頁面會呼叫其中一個具有斷點的 Managed 物件,應用程式將會停止,並將控制權移交給調試程式,您可以在其中逐步執行程式代碼,如圖 28 所示。
步驟 13:手動編譯和部署受控資料庫物件
SQL Server 專案可讓您輕鬆地建立、編譯及部署受控資料庫物件。 不幸的是,SQL Server 專案僅適用於 Visual Studio 的 Professional 和 Team Systems 版本。 如果您使用 Visual Web Developer 或 Standard Edition 的 Visual Studio,而且想要使用 Managed 資料庫物件,則必須手動建立和部署它們。 這牽涉到四個步驟:
- 建立包含Managed資料庫物件的原始程式碼的檔案,
- 將物件編譯成元件,
- 向 SQL Server 2005 資料庫註冊元件,以及
- 在 SQL Server 中建立指向元件中適當方法的資料庫物件。
為了說明這些工作,讓我們建立新的 Managed 預存程式,以傳回大於指定值的產品 UnitPrice
。 在您的電腦上建立名為 GetProductsWithPriceGreaterThan.cs
的新檔案,並在檔案中輸入下列程式代碼(您可以使用 Visual Studio、記事本或任何文字編輯器來完成此作業):
using System;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;
public partial class StoredProcedures
{
[Microsoft.SqlServer.Server.SqlProcedure]
public static void GetProductsWithPriceGreaterThan(SqlMoney price)
{
// Create the command
SqlCommand myCommand = new SqlCommand();
myCommand.CommandText =
@"SELECT ProductID, ProductName, SupplierID, CategoryID,
QuantityPerUnit, UnitPrice, UnitsInStock, UnitsOnOrder,
ReorderLevel, Discontinued
FROM Products
WHERE UnitPrice > @MinPrice";
myCommand.Parameters.AddWithValue("@MinPrice", price);
// Execute the command and send back the results
SqlContext.Pipe.ExecuteAndSend(myCommand);
}
};
此程式代碼與步驟 5 中建立的方法幾乎完全相同 GetProductsWithPriceLessThan
。 唯一的差異在於方法名稱、 WHERE
子句和查詢中使用的參數名稱。 回到 方法, GetProductsWithPriceLessThan
子 WHERE
句會讀取: WHERE UnitPrice < @MaxPrice
。 在這裡,在中 GetProductsWithPriceGreaterThan
,我們使用: WHERE UnitPrice > @MinPrice
。
我們現在必須將這個類別編譯成元件。 從命令行瀏覽至您儲存盤案的 GetProductsWithPriceGreaterThan.cs
目錄,並使用 C# 編譯程式 (csc.exe
) 將類別檔案編譯成元件:
csc.exe /t:library /out:ManuallyCreatedDBObjects.dll GetProductsWithPriceGreaterThan.cs
如果 包含在 csc.exe
中的資料夾不在系統 s PATH
中,您必須完整參考其路徑, %WINDOWS%\Microsoft.NET\Framework\version\
如下所示:
C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\csc.exe /t:library /out:ManuallyCreatedDBObjects.dll GetProductsWithPriceGreaterThan.cs
圖 29:編譯 GetProductsWithPriceGreaterThan.cs
成元件 (按兩下以檢視完整大小的映射)
旗 /t
標會指定 C# 類別檔案應該編譯成 DLL(而不是可執行檔)。 旗 /out
標會指定產生的元件名稱。
注意
您可以替代使用 Visual C# Express Edition 或在 Visual Studio Standard Edition 中建立個別的類別庫專案,而不是從命令行編譯GetProductsWithPriceGreaterThan.cs
類別檔案。 S 任 Jacob Lauritsen 已提供這類 Visual C# Express Edition 專案,其中包含預存程式的程式代碼 GetProductsWithPriceGreaterThan
,以及步驟 3、5 和 10 中建立的兩個 Managed 預存程式和 UDF。 S 任 專案也包含新增對應資料庫物件所需的 T-SQL 命令。
編譯成元件的程式代碼之後,我們即可在 SQL Server 2005 資料庫中註冊元件。 這可以透過 T-SQL、使用 命令 CREATE ASSEMBLY
或透過 SQL Server Management Studio 來執行。 讓我們專注於使用Management Studio。
從 Management Studio,展開 Northwind 資料庫中的 [可程式性] 資料夾。 其子資料夾之一是元件。 若要手動將新的元件新增至資料庫,請以滑鼠右鍵按兩下 [元件] 資料夾,然後從操作功能表中選擇 [新增元件]。 這會顯示 [新增元件] 對話框(請參閱圖 30)。 按兩下 [瀏覽] 按鈕,選取剛才編譯的 ManuallyCreatedDBObjects.dll
元件,然後按兩下 [確定] 將元件新增至資料庫。 您不應該在 ManuallyCreatedDBObjects.dll
物件總管 中看到元件。
圖 30:將 ManuallyCreatedDBObjects.dll
元件新增至資料庫 (按一下以檢視完整大小的影像)
圖 31:ManuallyCreatedDBObjects.dll
列在 物件總管
雖然我們已將元件新增至 Northwind 資料庫,但我們尚未將預存程式與 GetProductsWithPriceGreaterThan
元件中的方法產生關聯。 若要達成此目的,請開啟新的查詢視窗,然後執行下列腳本:
CREATE PROCEDURE [dbo].[GetProductsWithPriceGreaterThan]
(
@price money
)
WITH EXECUTE AS CALLER
AS
EXTERNAL NAME [ManuallyCreatedDBObjects].[StoredProcedures].[GetProductsWithPriceGreaterThan]
GO
這會在 Northwind 資料庫中建立名為 GetProductsWithPriceGreaterThan
的新預存程式,並將它與 Managed 方法 GetProductsWithPriceGreaterThan
產生關聯(其位於 類別 StoredProcedures
中,也就是元件 ManuallyCreatedDBObjects
中)。
執行上述文稿之後,請重新整理 物件總管 中的預存程序資料夾。 您應該會看到新的預存程式專案 - GetProductsWithPriceGreaterThan
旁邊有鎖定圖示。 若要測試此預存程式,請在查詢視窗中輸入並執行下列文稿:
exec GetProductsWithPriceGreaterThan 24.95
如圖 32 所示,上述命令會顯示大於 $24.95 的產品 UnitPrice
資訊。
圖 32:ManuallyCreatedDBObjects.dll
列在 物件總管 中 (按兩下以檢視完整大小的影像)
摘要
Microsoft SQL Server 2005 提供與 Common Language Runtime (CLR) 的整合,以允許使用 Managed 程式代碼建立資料庫物件。 先前,這些資料庫物件只能使用 T-SQL 來建立,但現在我們可以使用 C# 等 .NET 程式設計語言來建立這些物件。 在本教學課程中,我們建立了兩個受控預存程式和受控用戶定義函式。
Visual Studio 的 SQL Server 專案類型有助於建立、編譯及部署 Managed 資料庫物件。 此外,它提供豐富的偵錯支援。 不過,SQL Server 專案類型僅適用於 Visual Studio 的 Professional 和 Team Systems 版本。 對於使用 Visual Web Developer 或 Standard Edition 的 Visual Studio 的使用者,必須手動執行建立、編譯和部署步驟,如步驟 13 中所見。
快樂的程序設計!
深入閱讀
如需本教學課程中所討論主題的詳細資訊,請參閱下列資源:
- 用戶定義函式的優點和缺點
- 在Managed程式代碼中建立 SQL Server 2005 物件
- 如何:建立和執行 CLR SQL Server 預存程式
- 如何:建立和執行 CLR SQL Server 使用者定義函數
- 如何:編輯
Test.sql
文本以執行 SQL 物件 - 用戶定義函式簡介
- Managed 程序代碼和 SQL Server 2005 (影片)
- Transact-SQL 參考
- 逐步解說:在Managed程式代碼中建立預存程式
關於作者
斯科特·米切爾,七本 ASP/ASP.NET 書籍和 4GuysFromRolla.com 創始人的作者,自1998年以來一直與Microsoft Web 技術合作。 斯科特擔任獨立顧問、教練和作家。 他的最新書是 山姆斯在24小時內 ASP.NET 2.0。 他可以到達 mitchell@4GuysFromRolla.com, 或通過他的博客,可以在 找到 http://ScottOnWriting.NET。
特別感謝
本教學課程系列已由許多實用的檢閱者檢閱。 本教學課程的主要檢閱者是 S 任 Jacob Lauritsen。 除了檢閱本文之外,S 任也建立了本文下載隨附的 Visual C# Express Edition 專案,以手動編譯 Managed 資料庫物件。 有興趣檢閱我即將推出的 MSDN 文章嗎? 如果是,請將一行 mitchell@4GuysFromRolla.com放在 。