一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術(shù)|正則表達(dá)式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務(wù)器之家 - 編程語言 - ASP.NET教程 - 在ASP.NET 2.0中操作數(shù)據(jù)之六十五:在TableAdapters中創(chuàng)建新的存儲過程

在ASP.NET 2.0中操作數(shù)據(jù)之六十五:在TableAdapters中創(chuàng)建新的存儲過程

2020-01-10 15:42heker2007 ASP.NET教程

本文主要講解使用TableAdapter設(shè)置向?qū)ё詣觿?chuàng)建增刪改查的存儲過程,雖然自動創(chuàng)建存儲過程可以節(jié)省時間,但他們會包含一些無用的參數(shù),下節(jié)我們會介紹TableAdapter使用現(xiàn)有的存儲過程。

導(dǎo)言:

  本教程的Data Access Layer (DAL)使用的是類型化的數(shù)據(jù)集(Typed DataSets).就像我們在第一章《創(chuàng)建一個數(shù)據(jù)訪問層》里探討的一樣,該類型化的數(shù)據(jù)集由強(qiáng)類型的DataTable和TableAdapter構(gòu)成。DataTable描繪的是系統(tǒng)里的邏輯實體而TableAdapter引用相關(guān)數(shù)據(jù)庫執(zhí)行數(shù)據(jù)訪問,包括對DataTable填充數(shù)據(jù)、執(zhí)行返回標(biāo)量數(shù)據(jù)(scalar data)的請求、添加,更新,刪除數(shù)據(jù)庫里的記錄等.

  TableAdapter執(zhí)行的SQL命令要么是某個特定的SQL statements,比如SELECT columnList FROM TableName;要么是存儲過程.本教程前面部分的TableAdapter使用的是SQL statements.不過很多開發(fā)者和數(shù)據(jù)庫管理員基于安全、便于維護(hù)等方面的考慮,偏愛使用存儲過程;不過也有的人出于靈活性的考慮偏愛使用SQL statement.就我自己而言,我也偏向于存儲過程.在前面的文章,出于簡化的目的我選用的是SQL statements.

  當(dāng)定義一個新TableAdapter或添加新方法時,使用TableAdapter的設(shè)置向?qū)В覀兛梢院苋菀椎膭?chuàng)建新的或使用現(xiàn)有的存儲過程.在本文,我們將考察如何使用設(shè)置向?qū)ё詣拥纳a(chǎn)存儲過程。在下一章我們考察如何設(shè)置TableAdapter的方法使用現(xiàn)有的或手動創(chuàng)建存儲過程.

  注意:關(guān)于討論到底使用存儲過程還是使用SQL statements的問題,可參考Rob Howard的博客文章《Don't Use Stored Procedures Yet?》(http://weblogs.asp.net/rhoward/archive/2003/11/17/38095.aspx)和Frans Bouma的博客文章《Stored Procedures are Bad, M'Kay?》(http://weblogs.asp.net/fboue/2003/11/18/38178.aspx

存儲過程基礎(chǔ)

  一個存儲過程由一系列的T-SQL statement組成,當(dāng)調(diào)用該存儲過程時就執(zhí)行這些T-SQL statement.存儲過程可以接受0到多個輸入?yún)?shù),返回標(biāo)量值、輸出參數(shù),或最常見的返回SELECT查詢值.

  注意:存儲過程Stored procedures也經(jīng)常引用為“sprocs” or “SPs”.

  可以使用T-SQL statement語句CREATE PROCEDURE來創(chuàng)建存儲過程.比如下面的T-SQL腳本創(chuàng)建了一個名為GetProductsByCategoryID的存儲過程,它有一個名為 @CategoryID的參數(shù),并且將表Products里與CategoryID值相吻合的那條記錄的ProductID, ProductName, UnitPrice,以及Discontinued值返回.

?
1
2
3
4
5
6
7
8
9
CREATE PROCEDURE GetProductsByCategoryID
(
 @CategoryID int
)
AS
 
SELECT ProductID, ProductName, UnitPrice, Discontinued
FROM Products
WHERE CategoryID = @CategoryID

創(chuàng)建后,我們可以用下面的代碼調(diào)用它:

?
1
EXEC GetProductsByCategory categoryID

  注意:在下篇文章我們將在Visual Studio IDE集成環(huán)境里創(chuàng)建存儲過程.不過在本文,我們將用TableAdapter向?qū)碜詣觿?chuàng)建存儲過程.

  除了返回數(shù)據(jù)外,我們還可以在一個事務(wù)里用存儲過程執(zhí)行多條數(shù)據(jù)庫命令.比如,假如有一個名為DeleteCategory的存儲過程,其包含一個輸入?yún)?shù)@CategoryID,并執(zhí)行2個DELETE statemets,第一個是刪除相關(guān)的products,第二個是刪除category。存儲過程里面的多個statements并不是自動的封裝在一個事務(wù)里的.我們應(yīng)添加額外的T-SQL commands以確保存儲過程里的多條數(shù)據(jù)庫命令當(dāng)成原子操作處理.我們將在后面的內(nèi)容考察如何用事務(wù)來封裝存儲過程的命令.

  當(dāng)在體系的某個層使用存儲過程時,Data Access Layer的方法將調(diào)用某個具體的存儲過程而不是發(fā)出一個SQL statement命令.這樣一來我們可以發(fā)現(xiàn)、分析發(fā)出的查詢命令.并可以更清楚的看到數(shù)據(jù)庫是如何使用的.有關(guān)存儲過程基本原理的更多信息,可參考本文結(jié)束部分的延伸閱讀.

第一步:創(chuàng)建數(shù)據(jù)訪問層高級場景的Web頁面

在開始之前,讓我們花點時間創(chuàng)建本文及后面幾篇文章要用到的頁面。新建一個名為AdvancedDAL的文件夾,然后添加如下的ASP.NET頁面,記得使用母版頁Site.master:

Default.aspx
NewSprocs.aspx
ExistingSprocs.aspx
JOINs.aspx
AddingColumns.aspx
ComputedColumns.aspx
EncryptingConfigSections.aspx
ManagedFunctionsAndSprocs.aspx

在ASP.NET 2.0中操作數(shù)據(jù)之六十五:在TableAdapters中創(chuàng)建新的存儲過程
圖1:添加相關(guān)的頁面

像其它文件夾一樣,Default.aspx頁面將列出本部分的內(nèi)容,記得SectionLevelTutorialListing.ascx用戶控件提供了該功能。因此,將其從解決資源管理器里拖放到Default.aspx頁面.

在ASP.NET 2.0中操作數(shù)據(jù)之六十五:在TableAdapters中創(chuàng)建新的存儲過程
圖2:將SectionLevelTutorialListing.ascx用戶控件拖到Default.aspx頁面

最后,將這些頁面添加到Web.sitemap文件里。特別的,把下面的代碼放在“Working with Batched Data”

<siteMapNode>標(biāo)簽后面:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<siteMapNode url="~/AdvancedDAL/Default.aspx"
 title="Advanced DAL Scenarios"
 description="Explore a number of advanced Data Access Layer scenarios.">
 
 <siteMapNode url="~/AdvancedDAL/NewSprocs.aspx"
 title="Creating New Stored Procedures for TableAdapters"
 description="Learn how to have the TableAdapter wizard automatically
 create and use stored procedures." />
 <siteMapNode url="~/AdvancedDAL/ExistingSprocs.aspx"
 title="Using Existing Stored Procedures for TableAdapters"
 description="See how to plug existing stored procedures into a
 TableAdapter." />
 <siteMapNode url="~/AdvancedDAL/JOINs.aspx"
 title="Returning Data Using JOINs"
 description="Learn how to augment your DataTables to work with data
 returned from multiple tables via a JOIN query." />
 <siteMapNode url="~/AdvancedDAL/AddingColumns.aspx"
 title="Adding DataColumns to a DataTable"
 description="Master adding new columns to an existing DataTable." />
 <siteMapNode url="~/AdvancedDAL/ComputedColumns.aspx"
 title="Working with Computed Columns"
 description="Explore how to work with computed columns when using
 Typed DataSets." />
 <siteMapNode url="~/AdvancedDAL/EncryptingConfigSections.aspx"
 title="Protected Connection Strings in Web.config"
 description="Protect your connection string information in
 Web.config using encryption." />
 <siteMapNode url="~/AdvancedDAL/ManagedFunctionsAndSprocs.aspx"
 title="Creating Managed SQL Functions and Stored Procedures"
 description="See how to create SQL functions and stored procedures
 using managed code." />
</siteMapNode>

更新Web.sitemap文件后,花點時間在瀏覽器里查看,左邊的菜單將包括本部分的內(nèi)容.

在ASP.NET 2.0中操作數(shù)據(jù)之六十五:在TableAdapters中創(chuàng)建新的存儲過程
圖3:網(wǎng)站地圖現(xiàn)在包含了不部分的頁面

第二步:設(shè)置TableAdapter創(chuàng)建新的存儲過程

  我們在~/App_Code/DAL文件夾里創(chuàng)建一個類型化的DataSet,名稱為NorthwindWithSprocs.xsd.由于我們在以前的教程里已經(jīng)詳細(xì)探討了創(chuàng)建細(xì)節(jié),因此我們這里一筆帶過,如果你想知道詳細(xì)的創(chuàng)建過程請參閱前面的第1章《創(chuàng)建一個數(shù)據(jù)訪問層》在DAL文件夾上右擊鼠標(biāo)選“添加新項”,選DataSet模板,如圖4所示.

在ASP.NET 2.0中操作數(shù)據(jù)之六十五:在TableAdapters中創(chuàng)建新的存儲過程
圖4:新建一個名為NorthwindWithSprocs.xsd的數(shù)據(jù)集

  這樣將會創(chuàng)建一個新的類型化的DataSet,打開設(shè)計器,創(chuàng)建一個新的TableAdapter,展開TableAdapter設(shè)置向?qū)?向?qū)У牡谝徊绞亲屛覀冞x擇要連接的數(shù)據(jù)庫.在下拉列表里有一個連接到Northwind數(shù)據(jù)庫的連接字符串,選中它,再點下一步。接下來的界面讓我們選擇TableAdapter以哪種方式訪問數(shù)據(jù)庫.在以前的教程里我們選擇的是“Use SQL statements”,不過在本文我們選第二項:“Create new stored procedures”,點下一步.

在ASP.NET 2.0中操作數(shù)據(jù)之六十五:在TableAdapters中創(chuàng)建新的存儲過程
圖5:設(shè)置TableAdpater創(chuàng)建新的存儲過程

接下來,我們要指定主查詢(main query).我們將創(chuàng)建一個存儲過程來包含SELECT查詢.
使用下面的SELECT查詢:

?
1
2
3
4
SELECT ProductID, ProductName, SupplierID, CategoryID,
 QuantityPerUnit, UnitPrice, UnitsInStock, UnitsOnOrder,
 ReorderLevel, Discontinued
FROM Products

在ASP.NET 2.0中操作數(shù)據(jù)之六十五:在TableAdapters中創(chuàng)建新的存儲過程
圖6:鍵入SELECT查詢

  注意:在名為Northwind的數(shù)據(jù)集里的ProductsTableAdapter的主查詢與上面本文定義的主查詢有所不同。那個主查詢還返回了每個產(chǎn)品的category名稱和company名稱.不過在后面的文章我們將對本文的TableAdapter添加這些相關(guān)的代碼.再點“Advanced Options”按鈕.我們可以指定是否讓向?qū)門ableAdapter自動生成insert, update和delete statements;是否使用開發(fā)式并發(fā)操作(optimistic concurrency);是否完成inserts 和 update操作后刷新數(shù)據(jù)表.在默認(rèn)情況下,自動選中“Generate Insert, Update and Delete statements”選項。另外,本文不用選擇“Use optimistic concurrency”項.當(dāng)選擇自動創(chuàng)建存儲過程時,“Refresh the data table”項將被忽略掉.不管是否選中該項,最終的insert 和update存儲過程都會檢索剛添加或剛更新(just-inserted or just-updated record)的記錄,我們將在第三步看到.

在ASP.NET 2.0中操作數(shù)據(jù)之六十五:在TableAdapters中創(chuàng)建新的存儲過程
圖7:選中“Generate Insert, Update and Delete statements”項

  注意:當(dāng)選中“Use optimistic concurrency”項的時候,向?qū)赪HERE語句里添加額外的條件,當(dāng)其它列的值發(fā)生改動的話,將阻止數(shù)據(jù)更新.關(guān)于使用TableAdapter內(nèi)置的optimistic concurrency功能請參閱第21章《實現(xiàn)開放式并發(fā)》輸入SELECT主查詢并選取“Generate Insert, Update and Delete statements”項后,點下一步,接下來的界面,如圖8所示,讓我們?yōu)閟electing, inserting, updating, 和deleting數(shù)據(jù)的存儲過程命名.將這些存儲過程的名字改為Products_Select, Products_Insert, Products_Update, 和Products_Delete.

在ASP.NET 2.0中操作數(shù)據(jù)之六十五:在TableAdapters中創(chuàng)建新的存儲過程
圖8:為存儲過程重命名

向?qū)?chuàng)建了4個存儲過程,點“Preview SQL Script”按鈕,你可以在Preview SQL Script 對話框里將腳本保存在一個文件里或復(fù)制到剪貼板.

在ASP.NET 2.0中操作數(shù)據(jù)之六十五:在TableAdapters中創(chuàng)建新的存儲過程
圖9:預(yù)覽生成的存儲過程

  對存儲過程重命名后,點下一步,對TableAdapter相應(yīng)的方法命名.就像使用SQL statements一樣,我們可以創(chuàng)建方法來填充一個現(xiàn)有的DataTable或返回一個新的DataTable;我們也一個指定TableAdapter是否采用DB-Direct模式來插入、更新、刪除記錄.全選這3項,只不過將Return a DataTable方法重命名為GetProducts,如圖10所示:

在ASP.NET 2.0中操作數(shù)據(jù)之六十五:在TableAdapters中創(chuàng)建新的存儲過程
圖10:將方法重命名為Fill 和GetProducts

點Next總覽向?qū)?zhí)行的步驟.點Finish按鈕完成設(shè)置.一旦向?qū)ЫY(jié)束后,將返回DataSet設(shè)計器,它此時將包括ProductsDataTable.

在ASP.NET 2.0中操作數(shù)據(jù)之六十五:在TableAdapters中創(chuàng)建新的存儲過程
圖11:DataSet設(shè)計器將顯示剛剛添加的ProductsDataTable

第三步:考察剛剛創(chuàng)建的存儲過程

  我們在第二步里用向?qū)?chuàng)建了選擇、插入、更新、刪除數(shù)據(jù)的存儲過程.這些存儲過程可以通過Visual Studio查看或修改.打開服務(wù)器資源管理器,點到數(shù)據(jù)庫的存儲過程文件夾。如圖12所示,Northwind數(shù)據(jù)庫包含了4個新的存儲過程,Products_Delete, Products_Insert, Products_Select, and Products_Update.

在ASP.NET 2.0中操作數(shù)據(jù)之六十五:在TableAdapters中創(chuàng)建新的存儲過程
圖12:可以在Stored Procedures文件夾里找到我們創(chuàng)建的4個存儲過程

  注意:如果你看不到服務(wù)器資源管理器,點“View”菜單,選Server Explorer項.如果你無法找到新創(chuàng)建的存儲過程,右擊Stored Procedures文件夾,選“刷新”.

  要查看或修改某個存儲過程,在服務(wù)器資源管理器里雙擊其名字或右擊該存儲過程,選”打開“。如13顯示的是打開Products_Delete存儲過程的畫面.

在ASP.NET 2.0中操作數(shù)據(jù)之六十五:在TableAdapters中創(chuàng)建新的存儲過程
圖13:可以在Visual Studio里打開并修改存儲過程

Products_Delete和Products_Select存儲過程的內(nèi)容很好理解。比如下面的代碼構(gòu)成了Products_Insert存儲過程.

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
ALTER PROCEDURE dbo.Products_Insert
(
 @ProductName nvarchar(40),
 @SupplierID int,
 @CategoryID int,
 @QuantityPerUnit nvarchar(20),
 @UnitPrice money,
 @UnitsInStock smallint,
 @UnitsOnOrder smallint,
 @ReorderLevel smallint,
 @Discontinued bit
)
AS
 SET NOCOUNT OFF;
INSERT INTO [Products] ([ProductName], [SupplierID], [CategoryID], [QuantityPerUnit],
 [UnitPrice], [UnitsInStock], [UnitsOnOrder], [ReorderLevel], [Discontinued])
VALUES (@ProductName, @SupplierID, @CategoryID, @QuantityPerUnit, @UnitPrice,
 @UnitsInStock, @UnitsOnOrder, @ReorderLevel, @Discontinued);
 
SELECT ProductID, ProductName, SupplierID, CategoryID, QuantityPerUnit, UnitPrice,
 UnitsInStock, UnitsOnOrder, ReorderLevel, Discontinued
FROM Products
WHERE (ProductID = SCOPE_IDENTITY())

  在TableAdapter向?qū)Ю锒x的SELECT查詢返回Products表里的列,這些列又作為存儲過程的輸入?yún)?shù)并運(yùn)用到INSERT statement中.緊接著的是一個SELECT查詢,返回Products表里最新添加的記錄的各列的值(包括ProductID)。當(dāng)使用Batch Update模式添加一個新記錄時,刷新功能是很有用的。因為它將最新添加的ProductRow instances實例的ProductID屬性賦值為數(shù)據(jù)庫指派的自增值.

  下面的代碼說明了該功能.代碼創(chuàng)建了基于NorthwindWithSprocs數(shù)據(jù)集的ProductsTableAdapter以及ProductsDataTable。要向數(shù)據(jù)庫添加一個新的產(chǎn)品,我們要創(chuàng)建一個ProductsRow instance實例,對其賦值,并調(diào)用TableAdapter的Update方法,再傳遞給ProductsDataTable.在內(nèi)部,TableAdapter的Update方法遍歷傳遞給DataTable的所有ProductsRow instance實例(在本例,只有一個。因為我們只添加了一個產(chǎn)品),并執(zhí)行相應(yīng)的insert, update, 或delete命令。此時,執(zhí)行Products_Insert存儲過程,其向Products表添加一條新記錄,并返回該記錄的詳細(xì)信息,然后更新ProductsRow instance實例的ProductID值。Update方法完成后,我們就可以通過ProductsRow的ProductID屬性訪問新添加記錄的ProductID值了.

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// Create the ProductsTableAdapter and ProductsDataTable
NorthwindWithSprocsTableAdapters.ProductsTableAdapter productsAPI =
 new NorthwindWithSprocsTableAdapters.ProductsTableAdapter();
NorthwindWithSprocs.ProductsDataTable products =
 new NorthwindWithSprocs.ProductsDataTable();
 
// Create a new ProductsRow instance and set its properties
NorthwindWithSprocs.ProductsRow product = products.NewProductsRow();
product.ProductName = "New Product";
product.CategoryID = 1; // Beverages
product.Discontinued = false;
 
// Add the ProductsRow instance to the DataTable
products.AddProductsRow(product);
 
// Update the DataTable using the Batch Update pattern
productsAPI.Update(products);
 
// At this point, we can determine the value of the newly-added record's ProductID
int newlyAddedProductIDValue = product.ProductID;

類似的,Products_Update存儲過程的UPDATE statement后面也包含一個SELECT statement,如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
ALTER PROCEDURE dbo.Products_Update
(
 @ProductName nvarchar(40),
 @SupplierID int,
 @CategoryID int,
 @QuantityPerUnit nvarchar(20),
 @UnitPrice money,
 @UnitsInStock smallint,
 @UnitsOnOrder smallint,
 @ReorderLevel smallint,
 @Discontinued bit,
 @Original_ProductID int,
 @ProductID int
)
AS
 SET NOCOUNT OFF;
UPDATE [Products]
SET [ProductName] = @ProductName, [SupplierID] = @SupplierID,
 [CategoryID] = @CategoryID, [QuantityPerUnit] = @QuantityPerUnit,
 [UnitPrice] = @UnitPrice, [UnitsInStock] = @UnitsInStock,
 [UnitsOnOrder] = @UnitsOnOrder, [ReorderLevel] = @ReorderLevel,
 [Discontinued] = @Discontinued
WHERE (([ProductID] = @Original_ProductID));
 
SELECT ProductID, ProductName, SupplierID, CategoryID, QuantityPerUnit,
 UnitPrice, UnitsInStock, UnitsOnOrder, ReorderLevel, Discontinued
FROM Products
WHERE (ProductID = @ProductID)

  我們注意到該存儲過程有2個關(guān)于ProductID的參數(shù),即@Original_ProductID 和@ProductID,這樣以來我們就可以對主鍵值進(jìn)行改動了.舉個例子:有一個employee(雇員)數(shù)據(jù)庫,每條employee記錄都用雇員的社保號碼作為其主鍵值.要想更改某條記錄的社保號碼,必須提供新的號碼以及原始號碼.不過對Products表來說用不著,因為列ProductID是一個唯一標(biāo)識列(IDENTITY column),不應(yīng)對其更改.實際上,Products_Update存儲過程里的UPDATE statement并沒有包含ProductID列,因此,如果在UPDATE statement的WHERE字句里使用@Original_ProductID的話,顯得多此一舉,而應(yīng)該使用@ProductID參數(shù).當(dāng)更新某個存儲過程的參數(shù)時,TableAdapter里所有那些調(diào)用該存儲過程方法都應(yīng)該進(jìn)行更新.

第四步:修改存儲過程的參數(shù)并更新TableAdapter

  由于@Original_ProductID參數(shù)是多余的,讓我們將其從Products_Update存儲過程里完全清除.打開Products_Update存儲過程,刪除@Original_ProductID參數(shù),在UPDATE statement的WHERE字句里將@Original_ProductID改為@ProductID. 完成上述修改后,該存儲過程里的T-SQL看起來應(yīng)該和下面的差不多:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
ALTER PROCEDURE dbo.Products_Update
(
 @ProductName nvarchar(40),
 @SupplierID int,
 @CategoryID int,
 @QuantityPerUnit nvarchar(20),
 @UnitPrice money,
 @UnitsInStock smallint,
 @UnitsOnOrder smallint,
 @ReorderLevel smallint,
 @Discontinued bit,
 @ProductID int
)
AS
 SET NOCOUNT OFF;
UPDATE [Products] SET [ProductName] = @ProductName, [SupplierID] = @SupplierID,
 [CategoryID] = @CategoryID, [QuantityPerUnit] = @QuantityPerUnit,
 [UnitPrice] = @UnitPrice, [UnitsInStock] = @UnitsInStock,
 [UnitsOnOrder] = @UnitsOnOrder, [ReorderLevel] = @ReorderLevel,
 [Discontinued] = @Discontinued
WHERE (([ProductID] = @ProductID));
 
SELECT ProductID, ProductName, SupplierID, CategoryID, QuantityPerUnit,
 UnitPrice, UnitsInStock, UnitsOnOrder, ReorderLevel, Discontinued
FROM Products
WHERE (ProductID = @ProductID)

  按Ctrl+S或點工具欄里的“保存”圖標(biāo),保存更改.此時,Products_Update存儲過程不會執(zhí)行@Original_ProductID參數(shù),但TableAdapter仍然會傳遞該參數(shù).要想查看TableAdapter傳遞給Products_Update存儲過程的參數(shù),你可以在設(shè)計器里選中TableAdapter,轉(zhuǎn)到屬性窗口,點更新命令的參數(shù)集(UpdateCommand'sParameters collection)里的橢圓型區(qū)域,這樣將轉(zhuǎn)到Parameters Collection Editor對話框,如圖14所示:

在ASP.NET 2.0中操作數(shù)據(jù)之六十五:在TableAdapters中創(chuàng)建新的存儲過程
圖14:對話框里列出了傳遞給Products_Update存儲過程的參數(shù)

要刪除參數(shù),只需選中它,再點Remove按鈕.

  要刷新參數(shù)的話,你也可以在設(shè)計器里選中TableAdapter,點右鍵選“設(shè)置”,這將會開啟TableAdapter設(shè)置向?qū)В谐隽擞糜趕elect, insert, updat和delete的存儲過程,并列出了這些存儲過程的輸入?yún)?shù).如果你在Update下拉列表里選Products_Update的話,你可以看到該存儲過程包含的輸入?yún)?shù)里已經(jīng)沒有包含@Original_ProductID了(見圖15),點Finish將對TableAdapter使用的參數(shù)集自動更新.

 在ASP.NET 2.0中操作數(shù)據(jù)之六十五:在TableAdapters中創(chuàng)建新的存儲過程
圖15:你可以通過使用TableAdapter的設(shè)置向?qū)硭⑿聟?shù)集

第五步:添加額外的TableAdapter方法

  我們在第二步說過,當(dāng)創(chuàng)建一個新的TableAdapter時,很容易自動地生成相應(yīng)的存儲過程,同樣我們也可以向TableAdapter添加額外的方法.作為演示,讓我們向ProductsTableAdapter添加一個方法GetProductByProductID(productID),該方法將一個ProductID作為輸入?yún)?shù),并返回該產(chǎn)品的詳細(xì)信息.在ProductsTableAdapter上點擊右鍵,選擇“添加查詢”.

在ASP.NET 2.0中操作數(shù)據(jù)之六十五:在TableAdapters中創(chuàng)建新的存儲過程
圖16:向TableAdapter添加新查詢

  這將開啟TableAdapter查詢設(shè)置向?qū)АJ紫龋驅(qū)⒃儐栆院畏N方式訪問數(shù)據(jù)庫,我們將創(chuàng)建一個新的存儲過程,因此選“Create a new stored procedure”,再點Next.

在ASP.NET 2.0中操作數(shù)據(jù)之六十五:在TableAdapters中創(chuàng)建新的存儲過程
圖17:選中“Create a new stored procedure”項

  接下來,向?qū)г儐栁覀儓?zhí)行哪種查詢,是返回一系列行?一個標(biāo)量值?又或者執(zhí)行UPDATE, INSERT,或 DELETE statement.由于GetProductByProductID(productID)方法將返回一行,我們選擇“SELECT which returns row”項,再點Next.

在ASP.NET 2.0中操作數(shù)據(jù)之六十五:在TableAdapters中創(chuàng)建新的存儲過程
圖18:選擇“SELECT which returns row” 項

  接下來的界面將展示TableAdapter的主查詢,其僅僅列出了存儲過程的名字(也就是dbo.Products_Select).將其刪除,替換為如下的SELECT statement,它返回某個具體產(chǎn)品的所有列.

?
1
2
3
4
5
SELECT ProductID, ProductName, SupplierID, CategoryID,
 QuantityPerUnit, UnitPrice, UnitsInStock, UnitsOnOrder,
 ReorderLevel, Discontinued
FROM Products
WHERE ProductID = @ProductID

在ASP.NET 2.0中操作數(shù)據(jù)之六十五:在TableAdapters中創(chuàng)建新的存儲過程
圖19:將存儲過程的名字替換為一個SELECT查詢.

  接下來要對創(chuàng)建的存儲過程命名,輸入Products_SelectByProductID,點Next.

在ASP.NET 2.0中操作數(shù)據(jù)之六十五:在TableAdapters中創(chuàng)建新的存儲過程
圖20:將新存儲過程命名為Products_SelectByProductID

  最后一步將要我們對自動生成的名字重新命名,并指定是否使用Fill a DataTable模式、是否使用Return a DataTable模式,抑或這2種模式都采用.就本文而言,都選中這2項并將方法重命名為FillByProductID 和 GetProductByProductID.點Next,再點Finish完成設(shè)置向?qū)?

 在ASP.NET 2.0中操作數(shù)據(jù)之六十五:在TableAdapters中創(chuàng)建新的存儲過程

圖21:將TableAdapter的方法重命名為FillByProductID 和 GetProductByProductID

  完成向?qū)Ш螅琓ableAdapter將包含一個新的可用方法——GetProductByProductID(productID),當(dāng)調(diào)用該方法時,將執(zhí)行我們剛剛創(chuàng)建的Products_SelectByProductID存儲過程.花點時間在服務(wù)器資源管理器里查看該存儲過程,點Stored Procedures文件夾,并打開Products_SelectByProductID(如果你沒看到它,在Stored Procedures文件夾上右擊鼠標(biāo),選“刷新”).

  請注意,SelectByProductID存儲過程將@ProductID作為輸入?yún)?shù),并執(zhí)行我們在向?qū)Ю镙斎氲腟ELECT Statement,如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
ALTER PROCEDURE dbo.Products_SelectByProductID
(
 @ProductID int
)
AS
 SET NOCOUNT ON;
 
SELECT ProductID, ProductName, SupplierID, CategoryID,
 QuantityPerUnit, UnitPrice, UnitsInStock, UnitsOnOrder,
 ReorderLevel, Discontinued
FROM Products
WHERE ProductID = @ProductID

第六步:創(chuàng)建一個業(yè)務(wù)邏輯層類

在我們打算從表現(xiàn)層訪問產(chǎn)品前,我們首先需要為新添加的數(shù)據(jù)集創(chuàng)建一個BLL class,在~/App_Code/BLL文件夾里創(chuàng)建一個ProductsBLLWithSprocs.cs文件,如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
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;
using NorthwindWithSprocsTableAdapters;
 
[System.ComponentModel.DataObject]
public class ProductsBLLWithSprocs
{
 private ProductsTableAdapter _productsAdapter = null;
 protected ProductsTableAdapter Adapter
 {
 get
 {
  if (_productsAdapter == null)
  _productsAdapter = new ProductsTableAdapter();
 
  return _productsAdapter;
 }
 }
 
 [System.ComponentModel.DataObjectMethodAttribute
 (System.ComponentModel.DataObjectMethodType.Select, true)]
 public NorthwindWithSprocs.ProductsDataTable GetProducts()
 {
 return Adapter.GetProducts();
 }
 
 
 [System.ComponentModel.DataObjectMethodAttribute
 (System.ComponentModel.DataObjectMethodType.Select, false)]
 public NorthwindWithSprocs.ProductsDataTable GetProductByProductID(int productID)
 {
 return Adapter.GetProductByProductID(productID);
 }
 
 
 [System.ComponentModel.DataObjectMethodAttribute
 (System.ComponentModel.DataObjectMethodType.Insert, true)]
 public bool AddProduct
 (string productName, int? supplierID, int? categoryID,
  string quantityPerUnit, decimal? unitPrice, short? unitsInStock,
  short? unitsOnOrder, short? reorderLevel, bool discontinued)
 {
 // Create a new ProductRow instance
 NorthwindWithSprocs.ProductsDataTable products =
  new NorthwindWithSprocs.ProductsDataTable();
 NorthwindWithSprocs.ProductsRow product = products.NewProductsRow();
 
 product.ProductName = productName;
 if (supplierID == null)
  product.SetSupplierIDNull();
 else
  product.SupplierID = supplierID.Value;
 if (categoryID == null)
  product.SetCategoryIDNull();
 else
  product.CategoryID = categoryID.Value;
 if (quantityPerUnit == null)
  product.SetQuantityPerUnitNull();
 else
  product.QuantityPerUnit = quantityPerUnit;
 if (unitPrice == null)
  product.SetUnitPriceNull();
 else
  product.UnitPrice = unitPrice.Value;
 if (unitsInStock == null)
  product.SetUnitsInStockNull();
 else
  product.UnitsInStock = unitsInStock.Value;
 if (unitsOnOrder == null)
  product.SetUnitsOnOrderNull();
 else
  product.UnitsOnOrder = unitsOnOrder.Value;
 if (reorderLevel == null)
  product.SetReorderLevelNull();
 else
  product.ReorderLevel = reorderLevel.Value;
 product.Discontinued = discontinued;
 
 // Add the new product
 products.AddProductsRow(product);
 int rowsAffected = Adapter.Update(products);
 
 // Return true if precisely one row was inserted, otherwise false
 return rowsAffected == 1;
 }
 
 [System.ComponentModel.DataObjectMethodAttribute
 (System.ComponentModel.DataObjectMethodType.Update, true)]
 public bool UpdateProduct
 (string productName, int? supplierID, int? categoryID, string quantityPerUnit,
 decimal? unitPrice, short? unitsInStock, short? unitsOnOrder,
 short? reorderLevel, bool discontinued, int productID)
 {
 NorthwindWithSprocs.ProductsDataTable products =
  Adapter.GetProductByProductID(productID);
 if (products.Count == 0)
  // no matching record found, return false
  return false;
 
 NorthwindWithSprocs.ProductsRow product = products[0];
 
 product.ProductName = productName;
 if (supplierID == null)
  product.SetSupplierIDNull();
 else
  product.SupplierID = supplierID.Value;
 if (categoryID == null)
  product.SetCategoryIDNull();
 else
  product.CategoryID = categoryID.Value;
 if (quantityPerUnit == null)
  product.SetQuantityPerUnitNull();
 else
  product.QuantityPerUnit = quantityPerUnit;
 if (unitPrice == null)
  product.SetUnitPriceNull();
 else
  product.UnitPrice = unitPrice.Value;
 if (unitsInStock == null)
  product.SetUnitsInStockNull();
 else
  product.UnitsInStock = unitsInStock.Value;
 if (unitsOnOrder == null)
  product.SetUnitsOnOrderNull();
 else
  product.UnitsOnOrder = unitsOnOrder.Value;
 if (reorderLevel == null)
  product.SetReorderLevelNull();
 else
  product.ReorderLevel = reorderLevel.Value;
 product.Discontinued = discontinued;
 
 // Update the product record
 int rowsAffected = Adapter.Update(product);
 
 // Return true if precisely one row was updated, otherwise false
 return rowsAffected == 1;
 }
 
 [System.ComponentModel.DataObjectMethodAttribute
 (System.ComponentModel.DataObjectMethodType.Delete, true)]
 public bool DeleteProduct(int productID)
 {
 int rowsAffected = Adapter.Delete(productID);
 
 // Return true if precisely one row was deleted, otherwise false
 return rowsAffected == 1;
 }
}

  該類和以前章節(jié)所創(chuàng)建的ProductsBLL class類差不多,只是它用的是數(shù)據(jù)集 NorthwindWithSprocs的ProductsTableAdapter 和 ProductsDataTable object對象。與ProductsBLL類使用using NorthwindTableAdapters不同,ProductsBLLWithSprocs類使用的是using NorthwindWithSprocsTableAdapters.同樣的,該類的ProductsDataTable和 ProductsRow對象使用的是NorthwindWithSprocs命名空間.我們的ProductsBLLWithSprocs class類提供了2種數(shù)據(jù)訪問方法GetProducts() 和GetProductByProductID().另外,還有添加、更新、刪除單個產(chǎn)品的方法.

第七步:在表現(xiàn)層出來數(shù)據(jù)集NorthwindWithSprocs

  此時,我們以及對數(shù)據(jù)訪問層和業(yè)務(wù)邏輯層做了相關(guān)改動,接下來我們要創(chuàng)建一個ASP.NET頁面調(diào)用BLL的ProductsBLLWithSprocs class類以展示、更新、刪除記錄.

  打開AdvancedDAL文件夾里的NewSprocs.aspx頁面,從工具箱拖一個GridView控件到頁面,設(shè)置其ID為Products. 從GridView的智能標(biāo)簽將其綁定到一個名為ProductsDataSource的ObjectDataSource,設(shè)置其調(diào)用ProductsBLLWithSprocs類.

在ASP.NET 2.0中操作數(shù)據(jù)之六十五:在TableAdapters中創(chuàng)建新的存儲過程
圖22:設(shè)置ObjectDataSource調(diào)用ProductsBLLWithSprocs類

  SELECT標(biāo)簽的下拉列表里有2個方法,GetProducts()和GetProductByProductID().由于我們將在GridView里顯示所有的產(chǎn)品,所以我們選GetProducts()方法.在UPDATE, INSERT, 和DELETE標(biāo)簽里都只有一個方法,確保選中它們,點Finish按鈕。

  完成設(shè)置后,Visual Studio會向GridView添加BoundFields列以及一個CheckBoxField列, 啟用GridView控件的“編輯”和“刪除”功能.

在ASP.NET 2.0中操作數(shù)據(jù)之六十五:在TableAdapters中創(chuàng)建新的存儲過程
圖23:頁面包含一個可以分頁和排序的GridView控件.

  就像在以前的教程里探討過的一樣,完成ObjectDataSource的設(shè)置后,Visual Studio 會自動的將OldValuesParameterFormatString屬性設(shè)置為“original_{0}”. 為使數(shù)據(jù)修改功能正常工作,要么將該屬性刪除,要么將其設(shè)置為“{0}”.

  在我們完成設(shè)置、啟用“編輯”和“刪除”功能、將OldValuesParameterFormatString屬性設(shè)為其默認(rèn)值后,頁面的聲明代碼看起來應(yīng)該和下面的差不多:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
<asp:GridView ID="Products" runat="server" AutoGenerateColumns="False"
 DataKeyNames="ProductID" DataSourceID="ProductsDataSource">
 <Columns>
 <asp:CommandField ShowDeleteButton="True" ShowEditButton="True" />
 <asp:BoundField DataField="ProductID" HeaderText="ProductID"
  InsertVisible="False" ReadOnly="True"
  SortExpression="ProductID" />
 <asp:BoundField DataField="ProductName" HeaderText="ProductName"
  SortExpression="ProductName" />
 <asp:BoundField DataField="SupplierID" HeaderText="SupplierID"
  SortExpression="SupplierID" />
 <asp:BoundField DataField="CategoryID" HeaderText="CategoryID"
  SortExpression="CategoryID" />
 <asp:BoundField DataField="QuantityPerUnit" HeaderText="QuantityPerUnit"
  SortExpression="QuantityPerUnit" />
 <asp:BoundField DataField="UnitPrice" HeaderText="UnitPrice"
  SortExpression="UnitPrice" />
 <asp:BoundField DataField="UnitsInStock" HeaderText="UnitsInStock"
  SortExpression="UnitsInStock" />
 <asp:BoundField DataField="UnitsOnOrder" HeaderText="UnitsOnOrder"
  SortExpression="UnitsOnOrder" />
 <asp:BoundField DataField="ReorderLevel" HeaderText="ReorderLevel"
  SortExpression="ReorderLevel" />
 <asp:CheckBoxField DataField="Discontinued" HeaderText="Discontinued"
  SortExpression="Discontinued" />
 </Columns>
</asp:GridView>
 
<asp:ObjectDataSource ID="ProductsDataSource" runat="server"
 DeleteMethod="DeleteProduct" InsertMethod="AddProduct"
 SelectMethod="GetProducts" TypeName="ProductsBLLWithSprocs"
 UpdateMethod="UpdateProduct">
 <DeleteParameters>
 <asp:Parameter Name="productID" Type="Int32" />
 </DeleteParameters>
 <UpdateParameters>
 <asp:Parameter Name="productName" Type="String" />
 <asp:Parameter Name="supplierID" Type="Int32" />
 <asp:Parameter Name="categoryID" Type="Int32" />
 <asp:Parameter Name="quantityPerUnit" Type="String" />
 <asp:Parameter Name="unitPrice" Type="Decimal" />
 <asp:Parameter Name="unitsInStock" Type="Int16" />
 <asp:Parameter Name="unitsOnOrder" Type="Int16" />
 <asp:Parameter Name="reorderLevel" Type="Int16" />
 <asp:Parameter Name="discontinued" Type="Boolean" />
 <asp:Parameter Name="productID" Type="Int32" />
 </UpdateParameters>
 <InsertParameters>
 <asp:Parameter Name="productName" Type="String" />
 <asp:Parameter Name="supplierID" Type="Int32" />
 <asp:Parameter Name="categoryID" Type="Int32" />
 <asp:Parameter Name="quantityPerUnit" Type="String" />
 <asp:Parameter Name="unitPrice" Type="Decimal" />
 <asp:Parameter Name="unitsInStock" Type="Int16" />
 <asp:Parameter Name="unitsOnOrder" Type="Int16" />
 <asp:Parameter Name="reorderLevel" Type="Int16" />
 <asp:Parameter Name="discontinued" Type="Boolean" />
 </InsertParameters>
</asp:ObjectDataSource>

  此時,我們可以對GridView控件做些修改,比如在編輯界面里使用確認(rèn)控件,在CategoryID 和 SupplierID列放置DropDownList控件,當(dāng)點擊Delete按鈕時彈出確認(rèn)框等.由于在以前的教程我們探討過這些主題,我不打算在此多花筆墨。

  不管你做沒做這些改進(jìn),讓我們在瀏覽器里對頁面測試,如圖24所示.在GridView控件里每行都可以編輯和刪除.

在ASP.NET 2.0中操作數(shù)據(jù)之六十五:在TableAdapters中創(chuàng)建新的存儲過程
圖24:可以通過GridView對產(chǎn)品進(jìn)行查看、編輯、刪除

結(jié)語:

  類型化數(shù)據(jù)集里的TableAdapters可以通過ad-hoc SQL statement或存儲過程訪問數(shù)據(jù)庫里的數(shù)據(jù).當(dāng)處理存儲過程時,我們要么使用現(xiàn)有的存儲過程,要么使用TableAdapter向?qū)?chuàng)建一個基于SELECT查詢的新的存儲過程.在本文,我們考察了如何自動的創(chuàng)建一個存儲過程.

  雖然自動創(chuàng)建可以節(jié)省時間,但是在某些情況下,向?qū)ё詣觿?chuàng)建的存儲過程與我們的期望值還是有差距.比如自動創(chuàng)建的Products_Update存儲過程,它包含@Original_ProductID 和 @ProductID這2個參數(shù),但@Original_ProductID參數(shù)對我們來說是多余的.

在接下來的文章,我們將考察TableAdapter使用現(xiàn)有的存儲過程的情況.

  祝編程快樂!

作者簡介

  本系列教程作者 Scott Mitchell,著有六本ASP/ASP.NET方面的書,是4GuysFromRolla.com的創(chuàng)始人,自1998年以來一直應(yīng)用 微軟Web技術(shù)。希望對大家的學(xué)習(xí)ASP.NET有所幫助。

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 青草视频在线观看免费资源 | 欧美一区二区三区gg高清影视 | 热99re久久精品国产首页 | 美女和男人差差 | 成人免费观看www视频 | 日本特级a禁片在线播放 | 高h辣h双处全是肉军婚 | 小早川怜子息梦精在线播放 | 2020国产精品视频免费 | 97自拍视频在线观看 | ai换脸杨颖被啪在线观看 | free性日本 | 天堂中文在线观看 | 免费日本在线视频 | 66j8影院xxxx深夜| 免费网址视频在线看 | 精品亚洲视频在线观看 | 国产激情影院 | 小小水蜜桃视频高清在线播放 | 美女被视频网站看免费入口 | 亚洲激情综合 | 国产精品久久久久久久午夜片 | japanese秘书丝袜 | 青青在线视频免费 | h肉动漫在线视频无修无遮挡 | 特黄特a级特别特级特毛片 特黄a级三级三级野战 | 国产午夜精品一区二区三区不卡 | 日本老妇乱子伦中文视频 | 欧美日韩国产超高清免费看片 | 国内9lporm自拍视频区 | 亚洲久操| 四虎影视网址 | 97色资源 | 国产精品日韩欧美一区二区 | 国产在线乱子伦一区二区 | 久久热这里面只有精品 | 亚洲视屏在线观看 | jiuse在线| 免费xxxx日本大片在线观看 | 国产日韩欧美综合一区二区三区 | 色婷婷在线视频 |