作為開發(fā)人員,當(dāng)我們?cè)趯W(xué)習(xí)新技術(shù)時(shí),例子可能是我們最大的敵人。而教程往往設(shè)計(jì)得易于理解,但是同時(shí),它們常常加固了懶惰,低效性,甚至于危險(xiǎn)的編碼習(xí)慣。再也沒有比ADO.NET示例更能說(shuō)明問(wèn)題的了。在本文中,我們將準(zhǔn)備分析一下強(qiáng)類型對(duì)象對(duì)于你的數(shù)據(jù)庫(kù)開發(fā)的意義以及為什么在沒有例子的情況下你應(yīng)該在應(yīng)用程序中盡量使用強(qiáng)類型對(duì)象。
具體地說(shuō),我們將分析怎樣在Visual Studio 2005中創(chuàng)建和使用強(qiáng)類型DataSet。正如本文所探討的,相對(duì)于其它可選的弱類型化的數(shù)據(jù)存取技術(shù),強(qiáng)類型DataSet提供了很多優(yōu)點(diǎn);并且,借助于Visual Studio 2005,創(chuàng)建和使用強(qiáng)類型DataSet比以往更為容易。
二、 強(qiáng)類型對(duì)象基礎(chǔ)及優(yōu)點(diǎn)
為了理解強(qiáng)類型化的含義,不妨讓我們先考慮一下約會(huì)的例子。如果你是一個(gè)單身漢,那么,你盼望與什么類型的人約會(huì)呢?你可能已經(jīng)有了自己具體的標(biāo)準(zhǔn),如富裕且吸引人或可能是居住條件優(yōu)越而性感。無(wú)論你的條件如何,當(dāng)你決定想與誰(shuí)在一起呆更長(zhǎng)的時(shí)間時(shí),你都難免有一套自己的約會(huì)標(biāo)準(zhǔn)。如果你很明智,可以列出一個(gè)經(jīng)過(guò)事先深思熟慮的列表,這樣可以幫助你節(jié)約不必要的感情付出。把一項(xiàng)"非酗酒"的條件加入到你的約會(huì)標(biāo)準(zhǔn)中將會(huì)節(jié)約你大量的時(shí)間,并且允許你把你的時(shí)間和精力用于與更好的候選者約會(huì)。
你可能疑惑,這怎么能與編程進(jìn)行比較呢?請(qǐng)聽我的解釋。ADO.NET數(shù)據(jù)存取對(duì)象的設(shè)計(jì)是為了實(shí)現(xiàn)最大的靈活性。除非你遇到相當(dāng)大的麻煩,否則,當(dāng)你從
上面的DataRow就是非類型化的;結(jié)果,你必須以一個(gè)串形式作為你要查詢的列名來(lái)存取這個(gè)值(或者,使用這個(gè)列集合中的列的索引值)。很可能,這個(gè)列真正存在。一個(gè)DataRow列的數(shù)據(jù)類型是對(duì)象;我們假定FirstName列的基本數(shù)據(jù)類型是字符串,但是,我們必須顯式地把它轉(zhuǎn)化成一個(gè)字符串以便使用它。如果列名發(fā)生變化(例如,你把它改為PersonFirstName),那么編譯器是不能通知你的。千萬(wàn)不要這樣!因此,如果你的代碼看起來(lái)更象如下形式,那么你的生活就會(huì)更容易些而你的代碼將更為可靠:
在第二個(gè)例子中,我們擁有一個(gè)強(qiáng)類型行,并且我們知道FirstName屬性是字符串類型。在此,不會(huì)出現(xiàn)雜亂的列名,而且也不存在雜亂的對(duì)象轉(zhuǎn)換問(wèn)題。編譯器為我們作類型檢查,并且我們可以繼續(xù)進(jìn)行其它任務(wù)而不必?fù)?dān)心是否我們已經(jīng)正確輸入了列名。
對(duì)于所有其它列也是如此;總之,當(dāng)你能夠使用一個(gè)更為具體的類型時(shí),你永遠(yuǎn)不應(yīng)該使用一個(gè)泛型對(duì)象。但是,請(qǐng)等一下。該強(qiáng)類型對(duì)象出自何處?我想我能夠告訴你這些對(duì)象是為你自動(dòng)創(chuàng)建的。然而,正如要建立良好的關(guān)系需要時(shí)間和精力一樣,強(qiáng)類型化你的對(duì)象也需要付出其它努力。好的方面在于,這里所花費(fèi)的額外時(shí)間是值得的,而且節(jié)省了將來(lái)更多的花在調(diào)試上的時(shí)間。
存在若干種可以實(shí)現(xiàn)強(qiáng)類型化的方法,在本文余下的部分中,我們將討論怎樣在Visual Studio 2005中創(chuàng)建強(qiáng)類型DataSet;當(dāng)然,還將分析一下這樣做的優(yōu)點(diǎn)和缺點(diǎn)。
三、 在VS 2005中創(chuàng)建強(qiáng)類型DataSet
其實(shí),強(qiáng)類型DataSet是一些提前定義了它們自己的列與表的泛型DataSet,這樣編譯器已經(jīng)知道它們將會(huì)包含什么內(nèi)容。不是把你的數(shù)據(jù)包裝為一個(gè)"露指手套",一個(gè)強(qiáng)類型DataSet恰似一個(gè)"手套"。每一個(gè)Visual Studio的后續(xù)版本會(huì)使得強(qiáng)類型化一個(gè)DataSet的過(guò)程更為容易。在這個(gè)示例中,我們將使用來(lái)自于SQL Server 2005中的AdventureWorks數(shù)據(jù)庫(kù)。這只要簡(jiǎn)單地執(zhí)行如下步驟:
1. 打開Visual Studio,然后創(chuàng)建一個(gè)新的ASP.NET網(wǎng)站。
2. 在Solution Explorer中,占擊以添加一個(gè)新項(xiàng)并且選擇DataSet,并命名為AdventureWorks.xsd。Visual Studio推薦把這個(gè)DataSet文件放到App_Code文件夾下。
3. 這個(gè)AdventureWorks.xsd將在設(shè)計(jì)模式下打開,并且激活"TableAdapter Configuration"向?qū)А,F(xiàn)在,僅僅點(diǎn)擊一下"Cancel"即可。
4. 定位到Server Explorer工具箱,導(dǎo)航到你的SQL Server 2005數(shù)據(jù)庫(kù)和AdventureWorks數(shù)據(jù)庫(kù)。(如果你還沒有安裝AdventureWorks數(shù)據(jù)庫(kù)的話,你可以從微軟的SQL Server 2005 Samples and Sample Databases下載頁(yè)面下載它,還有另外的SQL Server 2005示例。)
5. 把SalesOrderHeader和SalesOrderDetail表拖動(dòng)到你的DataSet設(shè)計(jì)器窗口。現(xiàn)在,這個(gè)窗口應(yīng)該類似于下面的屏幕快照。注意,對(duì)于我們加入的每個(gè)表,Visual Studio都創(chuàng)建一個(gè)強(qiáng)類型DataTable(該名稱是基于原始的表)和一個(gè)TableAdapter。這個(gè)DataTable為我們定義了每一個(gè)列。這個(gè)表適配器是我們用來(lái)填充這個(gè)表的對(duì)象。缺省情況下,我們有一個(gè)Fill()方法,由它找到表中的每一行。

這個(gè)強(qiáng)類型DataSet將返回在這兩個(gè)表中的所有記錄。既然AdventureWorks 這個(gè)SQL查詢是一個(gè)簡(jiǎn)單的SELECT查詢,它有一個(gè)@OrderDate參數(shù)以進(jìn)一步縮小結(jié)果范圍。這樣可以防止我們返回 四、 在一個(gè)ASP.NET頁(yè)面上使用強(qiáng)類型DataSet 這段代碼是很簡(jiǎn)單的。我們創(chuàng)建SalesOrderHeaderTableAdapter的一個(gè)實(shí)例-我們將使用它來(lái)填充DataTable。注意,不是聲明一個(gè)泛型DataTable,我們聲明了一個(gè)SalesOrderHeaderDataTable類型的對(duì)象。為了填充這個(gè)DataTable,我們調(diào)用GetDateBy()方法并且傳遞給它一個(gè)DateTime對(duì)象。還要注意,甚至這個(gè)檢索命令也是強(qiáng)類型化的,因?yàn)槲覀儽仨殏鬟f一個(gè)DateTime對(duì)象,而不僅僅是一個(gè)泛型對(duì)象。下面的屏幕快照顯示了上面示例代碼的清晰結(jié)果。
SalesOrderID, RevisionNumber, OrderDate, DueDate, ShipDate,
Status, OnlineOrderFlag, SalesOrderNumber, PurchaseOrderNumber,
AccountNumber, CustomerID, ContactID, SalesPersonID, TerritoryID,
BillToAddressID, ShipToAddressID, ShipMethodID, CreditCardID,
CreditCardApprovalCode, CurrencyRateID, SubTotal, TaxAmt, Freight,
TotalDue, Comment, rowguid, ModifiedDate
FROM Sales.SalesOrderHeader
WHERE (OrderDate > @OrderDate)
通過(guò)創(chuàng)建強(qiáng)類型DataSet,我們可以僅通過(guò)編寫幾行代碼就可以實(shí)現(xiàn)容易地在一個(gè)ASP.NET頁(yè)面顯示這些數(shù)據(jù)。首先,在你的網(wǎng)站上創(chuàng)建一個(gè)ASP.NET頁(yè)面并且在設(shè)計(jì)模式中觀察它。然后,拖放一個(gè)GridView控件到其上,保持其ID為GridView1。打開ASP.NET頁(yè)面的源代碼并且在文件的頂部導(dǎo)入AdventureWorksTableAdapters命名空間(在C#中,該語(yǔ)法為:"using AdventureWorksTableAdapters;")。最后,把下列代碼添加到Page_Load事件處理器中:
SalesOrderHeaderTableAdapter salesAdapter =
new SalesOrderHeaderTableAdapter();
//得到發(fā)生于2004年7月1日之后的訂單
AdventureWorks.SalesOrderHeaderDataTable Orders =
salesAdapter.GetDataBy(new DateTime(2004, 7, 1));
//把訂單結(jié)果綁定到GridView
this.GridView1.DataSource = Orders;
this.GridView1.DataBind();
除了通過(guò)代碼把結(jié)果綁定到GridView外,你還可以使用一個(gè)ObjectDataSource,設(shè)置它的TypeName屬性為AdventureWorksTableAdapters.SalesOrderHeaderTableAdapter,并且把它的SelectMethod設(shè)置為GetData或GetDataBy。
五、 使用強(qiáng)類型DataSet插入、更新和刪除數(shù)據(jù)
在本文中,我們已經(jīng)看到了怎樣使用一個(gè)強(qiáng)類型DataSet從一個(gè)數(shù)據(jù)庫(kù)中選擇數(shù)據(jù)。然而,你還可以使用這些工具來(lái)插入、更新和刪除基本的數(shù)據(jù)庫(kù)數(shù)據(jù)。
除了不必編寫代碼來(lái)存取數(shù)據(jù)庫(kù)外,使用這個(gè)強(qiáng)類型化的DataSet的另外一個(gè)很大的優(yōu)點(diǎn)是,在此不存在編譯器不能檢查的字符串列名潛伏在我們的代碼并且我們不必進(jìn)行任何對(duì)象轉(zhuǎn)換。如果我們?cè)?jīng)改變過(guò)我們的數(shù)據(jù)庫(kù)模式,那么一旦我們更新我們的AdventureWorks.xsd文件,我們將注意到在編譯期間的存在于我們的應(yīng)用程序中的所有的巨大變化。
六、 小結(jié)
其實(shí),除了使用強(qiáng)類型DataSet外,還有另外的方法來(lái)實(shí)現(xiàn)你的應(yīng)用程序的強(qiáng)類型化。你可以創(chuàng)建定制類-比DataSet更為輕量級(jí)并且能夠正確地響應(yīng)于你的數(shù)據(jù)庫(kù)。而且,還有一些第三方軟件開發(fā)者提供工具來(lái)自動(dòng)化這一過(guò)程。其中,一個(gè)特別的產(chǎn)品是LLBLGen Pro,就是我比較喜歡的工具之一,我還寫了有關(guān)于它的一本書:《Rapid C# Windows Development: Visual Studio 2005, SQL Server 2005,and LLBLGen Pro》。另外一個(gè)流行的工具是CodeSmith。甚至微軟也在使用一個(gè)與之類似的工具-DLINQ,它仍處于測(cè)試階段,至少在下一年中不會(huì)上市。
如果你使用Visual Studio強(qiáng)類型DataSet方法,那么你不需要購(gòu)買任何另外的軟件-這是一個(gè)明顯的優(yōu)點(diǎn)。所有這些解決方案都有其各自不同的特征和優(yōu)點(diǎn),但是強(qiáng)類型化你的關(guān)系數(shù)據(jù)的主要優(yōu)點(diǎn)還在于:可靠性,更少的錯(cuò)誤和更少的調(diào)試時(shí)間花費(fèi);另外,分析數(shù)據(jù)庫(kù)模式變化的影響并實(shí)現(xiàn)它們也更為容易。最后,非常希望你已經(jīng)了解到強(qiáng)類型化的優(yōu)點(diǎn)。祝你幸運(yùn)!