![petshop4.0詳解(系統(tǒng)架構(gòu)設(shè)計(jì))_第1頁(yè)](http://file4.renrendoc.com/view/534bedfa2674f49d63acbd89ad1bf623/534bedfa2674f49d63acbd89ad1bf6231.gif)
![petshop4.0詳解(系統(tǒng)架構(gòu)設(shè)計(jì))_第2頁(yè)](http://file4.renrendoc.com/view/534bedfa2674f49d63acbd89ad1bf623/534bedfa2674f49d63acbd89ad1bf6232.gif)
![petshop4.0詳解(系統(tǒng)架構(gòu)設(shè)計(jì))_第3頁(yè)](http://file4.renrendoc.com/view/534bedfa2674f49d63acbd89ad1bf623/534bedfa2674f49d63acbd89ad1bf6233.gif)
![petshop4.0詳解(系統(tǒng)架構(gòu)設(shè)計(jì))_第4頁(yè)](http://file4.renrendoc.com/view/534bedfa2674f49d63acbd89ad1bf623/534bedfa2674f49d63acbd89ad1bf6234.gif)
![petshop4.0詳解(系統(tǒng)架構(gòu)設(shè)計(jì))_第5頁(yè)](http://file4.renrendoc.com/view/534bedfa2674f49d63acbd89ad1bf623/534bedfa2674f49d63acbd89ad1bf6235.gif)
版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、etshop4.0 詳解之一(系統(tǒng)架構(gòu)設(shè)計(jì)) t4.asp中獲得。 一、PetShop的系統(tǒng)架構(gòu)設(shè)計(jì)在軟件體系架構(gòu)設(shè)計(jì)中,分層式結(jié)構(gòu)是最常見(jiàn),也是最重要的一種結(jié)構(gòu)。微軟推薦的分層式結(jié)構(gòu)一般分為三層,從下至上分別為:數(shù)據(jù)訪問(wèn)層、業(yè)務(wù)邏輯層(又或成為領(lǐng)域?qū)樱?、表示層,如圖所示:圖一:三層的分層式結(jié)構(gòu)數(shù)據(jù)訪問(wèn)層:有時(shí)候也稱為是持久層,其功能主要是負(fù)責(zé)數(shù)據(jù)庫(kù)的訪問(wèn)。簡(jiǎn)單的說(shuō)法就是實(shí)現(xiàn)對(duì)數(shù)據(jù)表的Select,Insert,Update,; Delete的操作。如果要加入ORM的元素,那么就會(huì)包括對(duì)象和數(shù)據(jù)表之間的mapping,以及對(duì)象實(shí)體的持久化。在PetShop的數(shù)據(jù)訪問(wèn)層中,并沒(méi)有使用ORM,從而
2、導(dǎo)致了代碼量的增加,可以看作是整個(gè)設(shè)計(jì)實(shí)現(xiàn)中的一大敗筆。業(yè)務(wù)邏輯層:是整個(gè)系統(tǒng)的核心,它與這個(gè)系統(tǒng)的業(yè)務(wù)(領(lǐng)域)有關(guān)。以PetShop為例,業(yè)務(wù)邏輯層的相關(guān)設(shè)計(jì),均和網(wǎng)上寵物店特有的邏輯相關(guān),例如查詢寵物,下訂單,添加寵物到購(gòu)物車等等。如果涉及到數(shù)據(jù)庫(kù)的訪問(wèn),則調(diào)用數(shù)據(jù)訪問(wèn)層。表示層:是系統(tǒng)的UI部分,負(fù)責(zé)使用者與整個(gè)系統(tǒng)的交互。在這一層中,理想的狀態(tài)是不應(yīng)包括系統(tǒng)的業(yè)務(wù)邏輯。表示層中的邏輯代碼,僅與界面元素有關(guān)。在PetShop中,是利用ASP.Net來(lái)設(shè)計(jì)的,因此包含了許多Web控件和相關(guān)邏輯。分層式結(jié)構(gòu)究竟其優(yōu)勢(shì)何在?Martin Fowler在Patterns of Enterpris
3、e Application Architecture一書(shū)中給出了答案:1、開(kāi)發(fā)人員可以只關(guān)注整個(gè)結(jié)構(gòu)中的其中某一層;2、可以很容易的用新的實(shí)現(xiàn)來(lái)替換原有層次的實(shí)現(xiàn);3、可以降低層與層之間的依賴;4、有利于標(biāo)準(zhǔn)化;5、利于各層邏輯的復(fù)用。概括來(lái)說(shuō),分層式設(shè)計(jì)可以達(dá)至如下目的:分散關(guān)注、松散耦合、邏輯復(fù)用、標(biāo)準(zhǔn)定義。一個(gè)好的分層式結(jié)構(gòu),可以使得開(kāi)發(fā)人員的分工更加明確。一旦定義好各層次之間的接口,負(fù)責(zé)不同邏輯設(shè)計(jì)的開(kāi)發(fā)人員就可以分散關(guān)注,齊頭并進(jìn)。例如 UI人員只需考慮用戶界面的體驗(yàn)與操作,領(lǐng)域的設(shè)計(jì)人員可以僅關(guān)注業(yè)務(wù)邏輯的設(shè)計(jì),而數(shù)據(jù)庫(kù)設(shè)計(jì)人員也不必為繁瑣的用戶交互而頭疼了。每個(gè)開(kāi)發(fā)人員的任務(wù)得到
4、了確認(rèn),開(kāi)發(fā)進(jìn)度就可以迅速的提高。松散耦合的好處是顯而易見(jiàn)的。如果一個(gè)系統(tǒng)沒(méi)有分層,那么各自的邏輯都緊緊糾纏在一起,彼此間相互依賴,誰(shuí)都是不可替換的。一旦發(fā)生改變,則牽一發(fā)而動(dòng)全身,對(duì)項(xiàng)目的影響極為嚴(yán)重。降低層與層間的依賴性,既可以良好地保證未來(lái)的可擴(kuò)展,在復(fù)用性上也是優(yōu)勢(shì)明顯。每個(gè)功能模塊一旦定義好統(tǒng)一的接口,就可以被各個(gè)模塊所調(diào)用,而不用為相同的功能進(jìn)行重復(fù)地開(kāi)發(fā)。進(jìn)行好的分層式結(jié)構(gòu)設(shè)計(jì),標(biāo)準(zhǔn)也是必不可少的。只有在一定程度的標(biāo)準(zhǔn)化基礎(chǔ)上,這個(gè)系統(tǒng)才是可擴(kuò)展的,可替換的。而層與層之間的通信也必然保證了接口的標(biāo)準(zhǔn)化?!敖馃o(wú)足赤,人無(wú)完人”,分層式結(jié)構(gòu)也不可避免具有一些缺陷:1、降低了系統(tǒng)的性能
5、。這是不言而喻的。如果不采用分層式結(jié)構(gòu),很多業(yè)務(wù)可以直接造訪數(shù)據(jù)庫(kù),以此獲取相應(yīng)的數(shù)據(jù),如今卻必須通過(guò)中間層來(lái)完成。2、有時(shí)會(huì)導(dǎo)致級(jí)聯(lián)的修改。這種修改尤其體現(xiàn)在自上而下的方向。如果在表示層中需要增加一個(gè)功能,為保證其設(shè)計(jì)符合分層式結(jié)構(gòu),可能需要在相應(yīng)的業(yè)務(wù)邏輯層和數(shù)據(jù)訪問(wèn)層中都增加相應(yīng)的代碼。前面提到,PetShop的表示層是用ASP.Net設(shè)計(jì)的,也就是說(shuō),它應(yīng)是一個(gè)BS系統(tǒng)。在.Net中,標(biāo)準(zhǔn)的BS分層式結(jié)構(gòu)如下圖所示:圖二:.Net中標(biāo)準(zhǔn)的BS分層式結(jié)構(gòu)隨著PetShop版本的更新,其分層式結(jié)構(gòu)也在不斷的完善,例如PetShop2.0,就沒(méi)有采用標(biāo)準(zhǔn)的三層式結(jié)構(gòu),如圖三:圖三:PetSh
6、op 2.0的體系架構(gòu)從圖中我們可以看到,并沒(méi)有明顯的數(shù)據(jù)訪問(wèn)層設(shè)計(jì)。這樣的設(shè)計(jì)雖然提高了數(shù)據(jù)訪問(wèn)的性能,但也同時(shí)導(dǎo)致了業(yè)務(wù)邏輯層與數(shù)據(jù)訪問(wèn)的職責(zé)混亂。一旦要求支持的數(shù)據(jù)庫(kù)發(fā)生變化,或者需要修改數(shù)據(jù)訪問(wèn)的邏輯,由于沒(méi)有清晰的分層,會(huì)導(dǎo)致項(xiàng)目作大的修改。而隨著硬件系統(tǒng)性能的提高,以及充分利用緩存、異步處理 等機(jī)制,分層式結(jié)構(gòu)所帶來(lái)的性能影響幾乎可以忽略不計(jì)。PetShop3.0糾正了此前層次不明的問(wèn)題,將數(shù)據(jù)訪問(wèn)邏輯作為單獨(dú)的一層獨(dú)立出來(lái):圖四:PetShop 3.0的體系架構(gòu)圖五:PetShop 4.0的體系架構(gòu)圖六:數(shù)據(jù)訪問(wèn)層的模塊結(jié)構(gòu)圖可以看到,在數(shù)據(jù)訪問(wèn)層中,完全采用了“面向接口編程”思
7、想。抽象出來(lái)的IDAL模塊,脫離了與具體數(shù)據(jù)庫(kù)的依賴,從而使得整個(gè)數(shù)據(jù)訪問(wèn)層利于數(shù)據(jù) 庫(kù)遷移。DALFactory模塊專門(mén)管理DAL對(duì)象的創(chuàng)建,便于業(yè)務(wù)邏輯層訪問(wèn)。SQLServerDAL和OracleDAL模塊均實(shí)現(xiàn)IDAL模塊的接口,其中包含的邏輯就是對(duì)數(shù)據(jù)庫(kù)的Select,Insert,Update和Delete操作。因?yàn)閿?shù)據(jù)庫(kù)類型的不同,對(duì)數(shù)據(jù)庫(kù)的操作也有所不同, 代碼也會(huì)因此有所區(qū)別。此外,抽象出來(lái)的IDAL模塊,除了解除了向下的依賴之外,對(duì)于其上的業(yè)務(wù)邏輯層,同樣僅存在弱依賴關(guān)系,如下圖所示:圖七:業(yè)務(wù)邏輯層的模塊結(jié)構(gòu)圖圖七中BLL是業(yè)務(wù)邏輯層的核心模塊,它包含了整個(gè)系統(tǒng)的核心業(yè)務(wù)
8、。在業(yè)務(wù)邏輯層中,不能直接訪問(wèn)數(shù)據(jù)庫(kù),而必須通過(guò)數(shù)據(jù)訪問(wèn)層。注意圖中對(duì)數(shù)據(jù)訪 問(wèn)業(yè)務(wù)的調(diào)用,是通過(guò)接口模塊IDAL來(lái)完成的。既然與具體的數(shù)據(jù)訪問(wèn)邏輯無(wú)關(guān),則層與層之間的關(guān)系就是松散耦合的。如果此時(shí)需要修改數(shù)據(jù)訪問(wèn)層的具體實(shí)現(xiàn),只要不涉及到IDAL的接口定義,那么業(yè)務(wù)邏輯層就不會(huì)受到任何影響。畢竟,具體實(shí)現(xiàn)的SQLServerDAL和OracalDAL根本就與業(yè)務(wù)邏 輯層沒(méi)有半點(diǎn)關(guān)系。因?yàn)樵赑etShop 4.0中引入了異步處理機(jī)制。插入訂單的策略可以分為同步和異步,兩者的插入策略明顯不同,但對(duì)于調(diào)用者而言,插入訂單的接口是完全一樣的,所以 PetShop 4.0中設(shè)計(jì)了IBLLStrategy
9、模塊。雖然在IBLLStrategy模塊中,僅僅是簡(jiǎn)單的IOrderStategy,但同時(shí)也給出了一個(gè)范例和信息,那就是在業(yè)務(wù)邏輯的處理中,如果存在業(yè)務(wù)操作的多樣化,或者是今后可能的變化,均應(yīng)利用抽象的原理。或者使用接口,或者使用抽象類,從而脫離對(duì)具 體業(yè)務(wù)的依賴。不過(guò)在PetShop中,由于業(yè)務(wù)邏輯相對(duì)簡(jiǎn)單,這種思想體現(xiàn)得不夠明顯。也正因?yàn)榇?,PetShop將核心的業(yè)務(wù)邏輯都放到了一個(gè)模塊 BLL中,并沒(méi)有將具體的實(shí)現(xiàn)和抽象嚴(yán)格的按照模塊分開(kāi)。所以表示層和業(yè)務(wù)邏輯層之間的調(diào)用關(guān)系,其耦合度相對(duì)較高:圖八:表示層的模塊結(jié)構(gòu)圖在圖五中,各個(gè)層次中還引入了輔助的模塊,如數(shù)據(jù)訪問(wèn)層的Messagin
10、g模塊,是為異步插入訂單的功能提供,采用了MSMQ (Microsoft Messaging Queue)技術(shù)。而表示層的CacheDependency則提供緩存功能。這些特殊的模塊,我會(huì)在此后的文章中詳細(xì)介紹。petshop4.0 詳解之二(數(shù)據(jù)訪問(wèn)層之?dāng)?shù)據(jù)庫(kù)訪問(wèn)設(shè)計(jì)) 在系列一中,我從整體上分析了PetShop的架構(gòu)設(shè)計(jì),并提及了分層的概念。從本部分開(kāi)始,我將依次對(duì)各層進(jìn)行代碼級(jí)的分析,以求獲得更加細(xì)致而深入的理解。在PetShop 4.0中,由于引入了ASP.Net 2.0的一些新特色,所以數(shù)據(jù)層的內(nèi)容也更加的廣泛和復(fù)雜,包括:數(shù)據(jù)庫(kù)訪問(wèn)、Messaging、MemberShip、Pro
11、file四部分。在系列二中,我將介紹有關(guān)數(shù)據(jù)庫(kù)訪問(wèn)的設(shè)計(jì)。在PetShop中,系統(tǒng)需要處理的數(shù)據(jù)庫(kù)對(duì)象分為兩類:一是數(shù)據(jù)實(shí)體,對(duì)應(yīng)數(shù)據(jù)庫(kù)中相應(yīng)的數(shù)據(jù)表。它們沒(méi)有行為,僅用于表現(xiàn)對(duì)象的數(shù)據(jù)。這些實(shí)體類都被放到Model程序集中,例如數(shù)據(jù)表Order對(duì)應(yīng)的實(shí)體類OrderInfo,其類圖如下:這些對(duì)象并不具有持久化的功能,簡(jiǎn)單地說(shuō),它們是作為數(shù)據(jù)的載體,便于業(yè)務(wù)邏輯針對(duì)相應(yīng)數(shù)據(jù)表進(jìn)行讀/寫(xiě)操作。雖然這些類的屬性分別映射了數(shù)據(jù)表的列,而每一個(gè)對(duì)象實(shí)例也恰恰對(duì)應(yīng)于數(shù)據(jù)表的每一行,但這些實(shí)體類卻并不具備對(duì)應(yīng)的數(shù)據(jù)庫(kù)訪問(wèn)能力。由于數(shù)據(jù)訪問(wèn)層和業(yè)務(wù)邏輯層都將對(duì)這些數(shù)據(jù)實(shí)體進(jìn)行操作,因此程序集Model會(huì)被這
12、兩層的模塊所引用。第二類數(shù)據(jù)庫(kù)對(duì)象則是數(shù)據(jù)的業(yè)務(wù)邏輯對(duì)象。這里所指的業(yè)務(wù)邏輯,并非業(yè)務(wù)邏輯層意義上的領(lǐng)域(domain)業(yè)務(wù)邏輯(從這個(gè)意義上,我更傾向于將業(yè)務(wù)邏輯層稱為“領(lǐng)域邏輯層”),一般意義上說(shuō),這些業(yè)務(wù)邏輯即為基本的數(shù)據(jù)庫(kù)操作,包括Select,Insert,Update和Delete。由于這些業(yè)務(wù)邏輯對(duì)象,僅具有行為而與數(shù)據(jù)無(wú)關(guān),因此它們均被抽象為一個(gè)單獨(dú)的接口模塊IDAL,例如數(shù)據(jù)表Order對(duì)應(yīng)的接口IOrder:將數(shù)據(jù)實(shí)體與相關(guān)的數(shù)據(jù)庫(kù)操作分離出來(lái),符合面向?qū)ο蟮木?。首先,它體現(xiàn)了“職責(zé)分離”的原則。將數(shù)據(jù)實(shí)體與其行為分開(kāi),使得兩者之間依賴減弱,當(dāng)數(shù)據(jù)行為發(fā)生改變時(shí),并不影響
13、Model模塊中的數(shù)據(jù)實(shí)體對(duì)象,避免了因一個(gè)類職責(zé)過(guò)多、過(guò)大,從而導(dǎo)致該類的引用者發(fā)生“災(zāi)難性”的影響。其次,它體現(xiàn)了“抽象”的精神,或者說(shuō)是“面向接口編程”的最佳體現(xiàn)。抽象的接口模塊IDAL,與具體的數(shù)據(jù)庫(kù)訪問(wèn)實(shí)現(xiàn)完全隔離。這種與實(shí)現(xiàn)無(wú)關(guān)的設(shè)計(jì),保證了系統(tǒng)的可擴(kuò)展性,同時(shí)也保證了數(shù)據(jù)庫(kù)的可移植性。在PetShop中,可以支持SQL Server和Oracle,那么它們具體的實(shí)現(xiàn)就分別放在兩個(gè)不同的模塊SQLServerDAL、OracleDAL中。以O(shè)rder為例,在SQLServerDAL、OracleDAL兩個(gè)模塊中,有不同的實(shí)現(xiàn),但它們同時(shí)又都實(shí)現(xiàn)了IOrder接口,如圖:從數(shù)據(jù)庫(kù)的實(shí)
14、現(xiàn)來(lái)看,PetShop體現(xiàn)出了沒(méi)有ORM框架的臃腫與丑陋。由于要對(duì)數(shù)據(jù)表進(jìn)行Insert和Select操作,以SQL Server為例,就使用了SqlCommand,SqlParameter,SqlDataReader等對(duì)象,以完成這些操作。尤其復(fù)雜的是Parameter的傳遞,在PetShop中,使用了大量的字符串常量來(lái)保存參數(shù)的名稱。此外,PetShop還專門(mén)為SQL Server和Oracle提供了抽象的Helper類,包裝了一些常用的操作,如ExecuteNonQuery、ExecuteReader等方法。在沒(méi)有ORM的情況下,使用Helper類是一個(gè)比較好的策略,利用它來(lái)完成數(shù)據(jù)庫(kù)基
15、本操作的封裝,可以減少很多和數(shù)據(jù)庫(kù)操作有關(guān)的代碼,這體現(xiàn)了對(duì)象復(fù)用的原則。PetShop將這些Helper類統(tǒng)一放到DBUtility模塊中,不同數(shù)據(jù)庫(kù)的Helper類暴露的方法基本相同,只除了一些特殊的要求,例如Oracle中處理bool類型的方式就和SQL Server不同,從而專門(mén)提供了OraBit和OraBool方法。此外,Helper類中的方法均為static方法,以利于調(diào)用。OracleHelper的類圖如下:對(duì)于數(shù)據(jù)訪問(wèn)層來(lái)說(shuō),最頭疼的是SQL語(yǔ)句的處理。在早期的CS結(jié)構(gòu)中,由于未采用三層式架構(gòu)設(shè)計(jì),數(shù)據(jù)訪問(wèn)層和業(yè)務(wù)邏輯層是緊密糅合在一起的,因此,SQL語(yǔ)句遍布與系統(tǒng)的每一個(gè)角落
16、。這給程序的維護(hù)帶來(lái)極大的困難。此外,由于Oracle使用的是PL-SQL,而SQL Server和Sybase等使用的是T-SQL,兩者雖然都遵循了標(biāo)準(zhǔn)SQL的語(yǔ)法,但在很多細(xì)節(jié)上仍有區(qū)別,如果將SQL語(yǔ)句大量的使用到程序中,無(wú)疑為可能的數(shù)據(jù)庫(kù)移植也帶來(lái)了困難。最好的方法是采用存儲(chǔ)過(guò)程。這種方法使得程序更加整潔,此外,由于存儲(chǔ)過(guò)程可以以數(shù)據(jù)庫(kù)腳本的形式存在,也便于移植和修改。但這種方式仍然有缺陷。一是存儲(chǔ)過(guò)程的測(cè)試相對(duì)困難。雖然有相應(yīng)的調(diào)試工具,但比起對(duì)代碼的調(diào)試而言,仍然比較復(fù)雜且不方便。二是對(duì)系統(tǒng)的更新帶來(lái)障礙。如果數(shù)據(jù)庫(kù)訪問(wèn)是由程序完成,在.Net平臺(tái)下,我們僅需要在修改程序后,將重新
17、編譯的程序集xcopy到部署的服務(wù)器上即可。如果使用了存儲(chǔ)過(guò)程,出于安全的考慮,必須有專門(mén)的DBA重新運(yùn)行存儲(chǔ)過(guò)程的腳本,部署的方式受到了限制。我曾經(jīng)在一個(gè)項(xiàng)目中,利用一個(gè)專門(mén)的表來(lái)存放SQL語(yǔ)句。如要使用相關(guān)的SQL語(yǔ)句,就利用關(guān)鍵字搜索獲得對(duì)應(yīng)語(yǔ)句。這種做法近似于存儲(chǔ)過(guò)程的調(diào)用,但卻避免了部署上的問(wèn)題。然而這種方式卻在性能上無(wú)法得到保證。它僅適合于SQL語(yǔ)句較少的場(chǎng)景。不過(guò),利用良好的設(shè)計(jì),我們可以為各種業(yè)務(wù)提供不同的表來(lái)存放SQL語(yǔ)句。同樣的道理,這些SQL語(yǔ)句也可以存放到XML文件中,更有利于系統(tǒng)的擴(kuò)展或修改。不過(guò)前提是,我們需要為它提供專門(mén)的SQL語(yǔ)句管理工具。SQL語(yǔ)句的使用無(wú)法避
18、免,如何更好的應(yīng)用SQL語(yǔ)句也無(wú)定論,但有一個(gè)原則值得我們遵守,就是“應(yīng)該盡量讓SQL語(yǔ)句盡存在于數(shù)據(jù)訪問(wèn)層的具體實(shí)現(xiàn)中”。當(dāng)然,如果應(yīng)用ORM,那么一切就變得不同了。因?yàn)镺RM框架已經(jīng)為數(shù)據(jù)訪問(wèn)提供了基本的Select,Insert,Update和Delete操作了。例如在NHibernate中,我們可以直接調(diào)用ISession對(duì)象的Save方法,來(lái)Insert(或者說(shuō)是Create)一個(gè)數(shù)據(jù)實(shí)體對(duì)象:public void Insert(OrderInfo order) ISession s = Sessions.GetSession(); ITransaction trans = nul
19、l; try trans = s.BeginTransaction(); s.Save( order); trans.Commit(); finally s.Close(); 沒(méi)有SQL語(yǔ)句,也沒(méi)有那些煩人的Parameters,甚至不需要專門(mén)去考慮事務(wù)。此外,這樣的設(shè)計(jì),也是與數(shù)據(jù)庫(kù)無(wú)關(guān)的,NHibernate可以通過(guò)Dialect(方言)的機(jī)制支持不同的數(shù)據(jù)庫(kù)。唯一要做的是,我們需要為OrderInfo定義hbm文件。當(dāng)然,ORM框架并非是萬(wàn)能的,面對(duì)紛繁復(fù)雜的業(yè)務(wù)邏輯,它并不能完全消滅SQL語(yǔ)句,以及替代復(fù)雜的數(shù)據(jù)庫(kù)訪問(wèn)邏輯,但它卻很好的體現(xiàn)了“80/20(或90/10)法則”(也被稱為
20、“帕累托法則”),也就是說(shuō):花比較少(10%-20%)的力氣就可以解決大部分(80%-90%)的問(wèn)題,而要解決剩下的少部分問(wèn)題則需要多得多的努力。至少,那些在數(shù)據(jù)訪問(wèn)層中占據(jù)了絕大部分的CRUD操作,通過(guò)利用ORM框架,我們就僅需要付出極少數(shù)時(shí)間和精力來(lái)解決它們了。這無(wú)疑縮短了整個(gè)項(xiàng)目開(kāi)發(fā)的周期。還是回到對(duì)PetShop的討論上來(lái)?,F(xiàn)在我們已經(jīng)有了數(shù)據(jù)實(shí)體,數(shù)據(jù)對(duì)象的抽象接口和實(shí)現(xiàn),可以說(shuō)有關(guān)數(shù)據(jù)庫(kù)訪問(wèn)的主體就已經(jīng)完成了。留待我們的還有兩個(gè)問(wèn)題需要解決:1、數(shù)據(jù)對(duì)象創(chuàng)建的管理2、利于數(shù)據(jù)庫(kù)的移植在PetShop中,要?jiǎng)?chuàng)建的數(shù)據(jù)對(duì)象包括Order,Product,Category,Invento
21、ry,Item。在前面的設(shè)計(jì)中,這些對(duì)象已經(jīng)被抽象為對(duì)應(yīng)的接口,而其實(shí)現(xiàn)則根據(jù)數(shù)據(jù)庫(kù)的不同而有所不同。也就是說(shuō),創(chuàng)建的對(duì)象有多種類別,而每種類別又有不同的實(shí)現(xiàn),這是典型的抽象工廠模式的應(yīng)用場(chǎng)景。而上面所述的兩個(gè)問(wèn)題,也都可以通過(guò)抽象工廠模式來(lái)解決。標(biāo)準(zhǔn)的抽象工廠模式類圖如下:例如,創(chuàng)建SQL Server的Order對(duì)象如下:PetShopFactory factory = new SQLServerFactory();IOrder = factory.CreateOrder();要考慮到數(shù)據(jù)庫(kù)的可移植性,則factory必須作為一個(gè)全局變量,并在主程序運(yùn)行時(shí)被實(shí)例化。但這樣的設(shè)計(jì)雖然已經(jīng)達(dá)到
22、了“封裝變化”的目的,但在創(chuàng)建PetShopFactory對(duì)象時(shí),仍不可避免的出現(xiàn)了具體的類SQLServerFactory,也即是說(shuō),程序在這個(gè)層面上產(chǎn)生了與SQLServerFactory的強(qiáng)依賴。一旦整個(gè)系統(tǒng)要求支持Oracle,那么還需要修改這行代碼為:PetShopFactory factory = new oracleFactory();DataAccess類完全取代了前面創(chuàng)建的工廠類體系,它是一個(gè)sealed類,其中創(chuàng)建各種數(shù)據(jù)對(duì)象的方法,均為靜態(tài)方法。之所以能用這個(gè)類達(dá)到抽象工廠的目的,是因?yàn)榕渲梦募头瓷涞倪\(yùn)用,如下的代碼片斷所示:public sealed class Da
23、taAccess/ Look up the DAL implementation we should be using private static readonly string path = ConfigurationManager.AppSettings”WebDAL”; private static readonly string orderPath = ConfigurationManager.AppSettings”O(jiān)rdersDAL”;在PetShop中,這種依賴配置文件和反射創(chuàng)建對(duì)象的方式極其常見(jiàn),包括IBLLStategy、CacheDependencyFactory等等。這
24、些實(shí)現(xiàn)邏輯散布于整個(gè)PetShop系統(tǒng)中,在我看來(lái),是可以在此基礎(chǔ)上進(jìn)行重構(gòu)的。也就是說(shuō),我們可以為整個(gè)系統(tǒng)提供類似于“Service Locator”的實(shí)現(xiàn):public static class ServiceLocatorprivate static readonly string dalPath = ConfigurationManager.AppSettings”WebDAL”; private static readonly string orderPath = ConfigurationManager.AppSettings”O(jiān)rdersDAL”;/private static
25、readonly string orderStategyPath = ConfigurationManager.AppSettings”O(jiān)rderStrategyAssembly”;public static object LocateDALObject(string className)string fullPath = dalPath + “.” + className;return Assembly.Load(dalPath).CreateInstance(fullPath);public static object LocateDALOrderObject(string classNa
26、me)string fullPath = orderPath + “.” + className;return Assembly.Load(orderPath).CreateInstance(fullPath);public static object LocateOrderStrategyObject(string className)string fullPath = orderStategyPath + “.” + className;return Assembly.Load(orderStategyPath).CreateInstance(fullPath);/通過(guò)ServiceLoc
27、ator,將所有與配置文件相關(guān)的namespace值統(tǒng)一管理起來(lái),這有利于各種動(dòng)態(tài)創(chuàng)建對(duì)象的管理和未來(lái)的維護(hù)。petshop4.0 詳解之三(PetShop數(shù)據(jù)訪問(wèn)層之消息處理) 在進(jìn)行系統(tǒng)設(shè)計(jì)時(shí),除了對(duì)安全、事務(wù)等問(wèn)題給與足夠的重視外,性能也是一個(gè)不可避免的問(wèn)題所在,尤其是一個(gè)B/S結(jié)構(gòu)的軟件系統(tǒng),必須充分地考慮訪問(wèn)量、數(shù)據(jù)流量、服務(wù)器負(fù)荷的問(wèn)題。解決性能的瓶頸,除了對(duì)硬件系統(tǒng)進(jìn)行升級(jí)外,軟件設(shè)計(jì)的合理性尤為重要。在前面我曾提到,分層式結(jié)構(gòu)設(shè)計(jì)可能會(huì)在一定程度上影響數(shù)據(jù)訪問(wèn)的性能,然而與它給設(shè)計(jì)人員帶來(lái)的好處相比,幾乎可以忽略。要提供整個(gè)系統(tǒng)的性能,還可以從數(shù)據(jù)庫(kù)的優(yōu)化著手,例如連接池的使用
28、、建立索引、優(yōu)化查詢策略等等,例如在PetShop中就利用了數(shù)據(jù)庫(kù)的Cache,對(duì)于數(shù)據(jù)量較大的訂單數(shù)據(jù),則利用分庫(kù)的方式為其單獨(dú)建立了Order和Inventory數(shù)據(jù)庫(kù)。而在軟件設(shè)計(jì)上,比較有用的方式是利用多線程與異步處理方式。在PetShop4.0中,使用了Microsoft Messaging Queue(MSMQ)技術(shù)來(lái)完成異步處理,利用消息隊(duì)列臨時(shí)存放要插入的數(shù)據(jù),使得數(shù)據(jù)訪問(wèn)因?yàn)椴恍枰L問(wèn)數(shù)據(jù)庫(kù)從而提供了訪問(wèn)性能,至于隊(duì)列中的數(shù)據(jù),則等待系統(tǒng)空閑的時(shí)候再進(jìn)行處理,將其最終插入到數(shù)據(jù)庫(kù)中。PetShop4.0中的消息處理,主要分為如下幾部分:消息接口IMessaging、消息工廠M
29、essagingFactory、MSMQ實(shí)現(xiàn)MSMQMessaging以及數(shù)據(jù)后臺(tái)處理應(yīng)用程序OrderProcessor。從模塊化分上,PetShop自始自終地履行了“面向接口設(shè)計(jì)”的原則,將消息處理的接口與實(shí)現(xiàn)分開(kāi),并通過(guò)工廠模式封裝消息實(shí)現(xiàn)對(duì)象的創(chuàng)建,以達(dá)到松散耦合的目的。由于在PetShop中僅對(duì)訂單的處理使用了異步處理方式,因此在消息接口IMessaging中,僅定義了一個(gè)IOrder接口,其類圖如下: public orderInfo Receive(int timeout) base.timeout = TimeSpan.FromSeconds(Convert.ToDouble(
30、timeout); return Receive(); public void Send(OrderInfo orderMessage) / This method does not involve in distributed transaction and optimizes performance using Single type base.transactionType = MessageQueueTransactionType.Single; base.Send(orderMessage); 所以,最后的類圖應(yīng)該如下:注意在Order類的Receive()方法中,是用new關(guān)鍵字而
31、不是override關(guān)鍵字來(lái)重寫(xiě)其父類PetShopQueue的Receive()虛方法。因此,如果是實(shí)例化如下的對(duì)象,將會(huì)調(diào)用PetShopQueue的Receive()方法,而不是子類Order的Receive()方法:PetShopQueue queue = new order();queue.Receive();從設(shè)計(jì)上來(lái)看,由于PetShop采用“面向接口設(shè)計(jì)”的原則,如果我們要?jiǎng)?chuàng)建Order對(duì)象,應(yīng)該采用如下的方式:IOrder order = new order();order.Receive();考慮到IOrder的實(shí)現(xiàn)有可能的變化,PetShop仍然利用了工廠模式,將IOrd
32、er對(duì)象的創(chuàng)建用專門(mén)的工廠模塊進(jìn)行了封裝: order order = new order(); while (true) / queue timeout variables TimeSpan datetimeStarting = new TimeSpan(DateT int processedItems = 0; ArrayList queueOrders = new ArrayList(); using (TransactionScope ts = new TransactionScope(TransactionScopeOption.Required, tsTimeout) / Rece
33、ive the orders from the queue for (int j = 0; j batchSize; j+) try /only receive more queued orders if there is enough time if (elapsedTime + queueTimeout + transactionTimeout) tsTimeout.TotalSeconds) queueOrders.Add(order.ReceiveFromQueue(queueTimeout); else j = batchSize; / exit loop /batch comple
34、te or MSMQ receive timed out ts.Complete(); / Insert the order (a)synchrounously based on configuration orderInsertStrategy.Insert(order);在這里,運(yùn)用了一個(gè)策略模式,類圖如下所示:Microsoft Messaging Queue(MSMQ)技術(shù)除用于異步處理以外,它主要還是一種分布式處理技術(shù)。分布式處理中,一個(gè)重要的技術(shù)要素就是有關(guān)消息的處理,而在System.Messaging命名空間中,已經(jīng)提供了Message類,可以用于承載消息的傳遞,前提上消息的發(fā)
35、送方與接收方在數(shù)據(jù)定義上應(yīng)有統(tǒng)一的接口規(guī)范。MSMQ在分布式處理的運(yùn)用,在我參與的項(xiàng)目中已經(jīng)有了實(shí)現(xiàn)。在為一個(gè)汽車制造商開(kāi)發(fā)一個(gè)大型系統(tǒng)時(shí),分銷商Dealer作為.Net客戶端,需要將數(shù)據(jù)傳遞到管理中心,并且該數(shù)據(jù)將被Oracle的EBS(E-Business System)使用。由于分銷商管理系統(tǒng)(DMS)采用的是C/S結(jié)構(gòu),數(shù)據(jù)庫(kù)為SQL Server,而汽車制造商管理中心的EBS數(shù)據(jù)庫(kù)為Oracle。這里就涉及到兩個(gè)系統(tǒng)之間數(shù)據(jù)的傳遞。實(shí)現(xiàn)架構(gòu)如下: 首先Dealer的數(shù)據(jù)通過(guò)MSMQ傳遞到MSMQ Server,此時(shí)可以將數(shù)據(jù)插入到SQL Server數(shù)據(jù)庫(kù)中,同時(shí)利用FTP將數(shù)據(jù)傳送
36、到專門(mén)的文件服務(wù)器上。然后利用IBM的EAI技術(shù)(企業(yè)應(yīng)用集成,Enterprise Application Itegration)定期將文件服務(wù)器中的文件,利用接口規(guī)范寫(xiě)入到EAI數(shù)據(jù)庫(kù)服務(wù)器中,并最終寫(xiě)道EBS的Oracle數(shù)據(jù)庫(kù)中。上述架構(gòu)是一個(gè)典型的分布式處理結(jié)構(gòu),而技術(shù)實(shí)現(xiàn)的核心就是MSMQ和EAI。由于我們已經(jīng)定義了統(tǒng)一的接口規(guī)范,在通過(guò)消息隊(duì)列形成文件后,此時(shí)的數(shù)據(jù)就已經(jīng)與平臺(tái)無(wú)關(guān)了,使得在.Net平臺(tái)下的分銷商管理系統(tǒng)能夠與Oracle的EBS集成起來(lái),完成數(shù)據(jù)的處理。petshop4.0 詳解之四(PetShop之ASP.NET緩存)如果對(duì)微型計(jì)算機(jī)硬件系統(tǒng)有足夠的了解,那么
37、我們對(duì)于Cache這個(gè)名詞一定是耳熟能詳?shù)?。在CPU以及主板的芯片中,都引入了這種名為高速緩沖存儲(chǔ)器(Cache)的技術(shù)。因?yàn)镃ache的存取速度比內(nèi)存快,因而引入Cache能夠有效的解決CPU與內(nèi)存之間的速度不匹配問(wèn)題。硬件系統(tǒng)可以利用Cache存儲(chǔ)CPU訪問(wèn)概率高的那些數(shù)據(jù),當(dāng)CPU需要訪問(wèn)這些數(shù)據(jù)時(shí),可以直接從Cache中讀取,而不必訪問(wèn)存取速度相對(duì)較慢的內(nèi)存,從而提高了CPU的工作效率。軟件設(shè)計(jì)借鑒了硬件設(shè)計(jì)中引入緩存的機(jī)制以改善整個(gè)系統(tǒng)的性能,尤其是對(duì)于一個(gè)數(shù)據(jù)庫(kù)驅(qū)動(dòng)的Web應(yīng)用程序而言,緩存的利用是不可或缺的,畢竟,數(shù)據(jù)庫(kù)查詢可能是整個(gè)Web站點(diǎn)中調(diào)用最頻繁但同時(shí)又是執(zhí)行最緩慢的操
38、作之一,我們不能被它老邁的雙腿拖緩我們前進(jìn)的征程。緩存機(jī)制正是解決這一缺陷的加速器。ASP.NET緩存概述作為.Net框架下開(kāi)發(fā)Web應(yīng)用程序的主打產(chǎn)品,ASP.NET充分考慮了緩存機(jī)制。通過(guò)某種方法,將系統(tǒng)需要的數(shù)據(jù)對(duì)象、Web頁(yè)面存儲(chǔ)在內(nèi)存中,使得Web站點(diǎn)在需要獲取這些數(shù)據(jù)時(shí),不需要經(jīng)過(guò)繁瑣的數(shù)據(jù)庫(kù)連接、查詢和復(fù)雜的邏輯運(yùn)算,就可以“觸手可及”,如“探囊取物”般容易而快速,從而提高整個(gè)Web系統(tǒng)的性能。ASP.NET提供了兩種基本的緩存機(jī)制來(lái)提供緩存功能。一種是應(yīng)用程序緩存,它允許開(kāi)發(fā)者將程序生成的數(shù)據(jù)或報(bào)表業(yè)務(wù)對(duì)象放入緩存中。另外一種緩存機(jī)制是頁(yè)輸出緩存,利用它,可以直接獲取存放在緩存
39、中的頁(yè)面,而不需要經(jīng)過(guò)繁雜的對(duì)該頁(yè)面的再次處理。應(yīng)用程序緩存其實(shí)現(xiàn)原理說(shuō)來(lái)平淡無(wú)奇,僅僅是通過(guò)ASP.NET管理內(nèi)存中的緩存空間。放入緩存中的應(yīng)用程序數(shù)據(jù)對(duì)象,以鍵/值對(duì)的方式存儲(chǔ),這便于用戶在訪問(wèn)緩存中的數(shù)據(jù)項(xiàng)時(shí),可以根據(jù)key值判斷該項(xiàng)是否存在緩存中。放入在緩存中的數(shù)據(jù)對(duì)象其生命周期是受到限制的,即使在整個(gè)應(yīng)用程序的生命周期里,也不能保證該數(shù)據(jù)對(duì)象一直有效。ASP.NET可以對(duì)應(yīng)用程序緩存進(jìn)行管理,例如當(dāng)數(shù)據(jù)項(xiàng)無(wú)效、過(guò)期或內(nèi)存不足時(shí)移除它們。此外,調(diào)用者還可以通過(guò)CacheItemRemovedCallback委托,定義回調(diào)方法使得數(shù)據(jù)項(xiàng)被移除時(shí)能夠通知用戶。我們還可以為應(yīng)用程序緩存添加依
40、賴項(xiàng),使得依賴項(xiàng)發(fā)生更改時(shí),該數(shù)據(jù)項(xiàng)能夠從緩存中移除:string dependencies = Second;Cache.Insert(Third, Third Item,new Syst與之對(duì)應(yīng)的是緩存中數(shù)據(jù)項(xiàng)的移除。前面提到ASP.NET可以自動(dòng)管理緩存中項(xiàng)的移除,但我們也可以通過(guò)代碼編寫(xiě)的方式顯式的移除相關(guān)的數(shù)據(jù)項(xiàng):Cache.Remove(First);相對(duì)于應(yīng)用程序緩存而言,頁(yè)輸出緩存的應(yīng)用更為廣泛。它可以通過(guò)內(nèi)存將處理后的ASP.NET頁(yè)面存儲(chǔ)起來(lái),當(dāng)客戶端再一次訪問(wèn)該頁(yè)面時(shí),可以省去頁(yè)面處理的過(guò)程,從而提高頁(yè)面訪問(wèn)的性能,以及Web服務(wù)器的吞吐量。例如,在一個(gè)電子商務(wù)網(wǎng)站里,用
41、戶需要經(jīng)常查詢商品信息,這個(gè)過(guò)程會(huì)涉及到數(shù)據(jù)庫(kù)訪問(wèn)以及搜索條件的匹配,在數(shù)據(jù)量較大的情況下,如此的搜索過(guò)程是較為耗時(shí)的。此時(shí),利用頁(yè)輸出緩存就可以將第一次搜索得到的查詢結(jié)果頁(yè)存儲(chǔ)在緩存中。當(dāng)用戶第二次查詢時(shí),就可以省去數(shù)據(jù)查詢的過(guò)程,減少頁(yè)面的響應(yīng)時(shí)間。頁(yè)輸出緩存分為整頁(yè)緩存和部分頁(yè)緩存。我們可以通過(guò)OutputCache指令完成對(duì)Web頁(yè)面的輸出緩存。它主要包含兩個(gè)參數(shù):Duration和VaryByParam。Duration參數(shù)用于設(shè)置頁(yè)面或控件進(jìn)行緩存的時(shí)間,其單位為秒。如下的設(shè)置表示緩存在60秒內(nèi)有效:只要沒(méi)有超過(guò)Duration設(shè)置的期限值,當(dāng)用戶訪問(wèn)相同的頁(yè)面或控件時(shí),就可以直接
42、在緩存中獲取。使用VaryByParam參數(shù)可以根據(jù)設(shè)置的參數(shù)值建立不同的緩存。例如在一個(gè)輸出天氣預(yù)報(bào)結(jié)果的頁(yè)面中,如果需要為一個(gè)ID為txtCity的TextBox控件建立緩存,其值將顯示某城市的氣溫,那么我們可以進(jìn)行如下的設(shè)置:如此一來(lái),ASP.NET會(huì)對(duì)txtCity控件的值進(jìn)行判斷,只有輸入的值與緩存值相同,才從緩存中取出相應(yīng)的值。這就有效地避免了因?yàn)橹档牟煌鴮?dǎo)致輸出錯(cuò)誤的數(shù)據(jù)。利用緩存的機(jī)制對(duì)性能的提升非常明顯。通過(guò)ACT(Application Center Test)的測(cè)試,可以發(fā)現(xiàn)設(shè)置緩存后執(zhí)行的性能比未設(shè)置緩存時(shí)的性能足足提高三倍多。引入緩存看來(lái)是提高性能的“完美”解決方案
43、,然而“金無(wú)足赤,人無(wú)完人”,緩存機(jī)制也有缺點(diǎn),那就是數(shù)據(jù)過(guò)期的問(wèn)題。一旦應(yīng)用程序數(shù)據(jù)或者頁(yè)面結(jié)果值發(fā)生的改變,那么在緩存有效期范圍內(nèi),你所獲得的結(jié)果將是過(guò)期的、不準(zhǔn)確的數(shù)據(jù)。我們可以想一想股票系統(tǒng)利用緩存所帶來(lái)的災(zāi)難,當(dāng)你利用錯(cuò)誤過(guò)期的數(shù)據(jù)去分析股市的風(fēng)云變幻時(shí),你會(huì)發(fā)現(xiàn)獲得的結(jié)果真可以說(shuō)是“失之毫厘,謬以千里”,看似大好的局面就會(huì)像美麗的泡沫一樣,用針一戳,轉(zhuǎn)眼就消失得無(wú)影無(wú)蹤。那么我們是否應(yīng)該為了追求高性能,而不顧所謂“數(shù)據(jù)過(guò)期”所帶來(lái)的隱患呢?顯然,在類似于股票系統(tǒng)這種數(shù)據(jù)更新頻繁的特定場(chǎng)景下,數(shù)據(jù)過(guò)期的糟糕表現(xiàn)甚至比低效的性能更讓人難以接受。故而,我們需要在性能與數(shù)據(jù)正確性間作出權(quán)衡
44、。所幸的是,.Net Framework 2.0引入了一種新的緩存機(jī)制,它為我們的“魚(yú)與熊掌兼得”帶來(lái)了技術(shù)上的可行性。.Net 2.0引入的自定義緩存依賴項(xiàng),特別是基于MS-SQL Server的SqlCacheDependency特性,使得我們可以避免“數(shù)據(jù)過(guò)期”的問(wèn)題,它能夠根據(jù)數(shù)據(jù)庫(kù)中相應(yīng)數(shù)據(jù)的變化,通知緩存,并移除那些過(guò)期的數(shù)據(jù)。事實(shí)上,在PetShop 4.0中,就充分地利用了SqlCacheDependency特性。SqlCacheDependency特性要使得7.0或者2000版本的SQL Server支持SqlCacheDependency特性,需要對(duì)數(shù)據(jù)庫(kù)服務(wù)器執(zhí)行相關(guān)的配
45、置步驟。有兩種方法配置SQL Server:使用aspnet_regsql命令行工具,或者使用SqlCacheDependencyAdmin類。利用aspnet_regsql工具aspnet_regsql工具位于WindowsMicrosoft.NETFramework版本文件夾中。如果直接雙擊該工具的執(zhí)行文件,會(huì)彈出一個(gè)向?qū)?duì)話框,提示我們完成相應(yīng)的操作:圖4-1 aspnet_regsql工具如圖4-1所示中的提示信息,說(shuō)明該向?qū)е饕糜谂渲肧QL Server數(shù)據(jù)庫(kù),如membership,profiles等信息,如果要配置SqlCacheDependency,則需要以命令行的方式執(zhí)行。
46、以PetShop 4.0為例,數(shù)據(jù)庫(kù)名為MSPetShop4,則命令為:aspnet_regsql -S localhost -E -d MSPetShop4 -ed以下是該工具的命令參數(shù)說(shuō)明:-? 顯示該工具的幫助功能;-S 后接的參數(shù)為數(shù)據(jù)庫(kù)服務(wù)器的名稱或者IP地址;-U 后接的參數(shù)為數(shù)據(jù)庫(kù)的登陸用戶名;-P 后接的參數(shù)為數(shù)據(jù)庫(kù)的登陸密碼;-E 當(dāng)使用windows集成驗(yàn)證時(shí),使用該功能;-d 后接參數(shù)為對(duì)哪一個(gè)數(shù)據(jù)庫(kù)采用SqlCacheDependency功能;-t 后接參數(shù)為對(duì)哪一個(gè)表采用SqlCacheDependency功能;-ed 允許對(duì)數(shù)據(jù)庫(kù)使用SqlCacheDependen
47、cy功能;-dd 禁止對(duì)數(shù)據(jù)庫(kù)采用SqlCacheDependency功能;-et 允許對(duì)數(shù)據(jù)表采用SqlCacheDependency功能;-dt 禁止對(duì)數(shù)據(jù)表采用SqlCacheDependency功能;-lt 列出當(dāng)前數(shù)據(jù)庫(kù)中有哪些表已經(jīng)采用sqlcachedependency功能。以上面的命令為例,說(shuō)明將對(duì)名為MSPetShop4的數(shù)據(jù)庫(kù)采用SqlCacheDependency功能,且SQL Server采用了windows集成驗(yàn)證方式。我們還可以對(duì)相關(guān)的數(shù)據(jù)表執(zhí)行aspnet_regsql命令,如:aspnet_regsql -S localhost -E -d MSPetShop4
48、 -t Item -etaspnet_regsql -S localhost -E -d MSPetShop4 -t Product -etaspnet_regsql -S localhost -E -d MSPetShop4 -t Category -et當(dāng)執(zhí)行上述的四條命令后,aspnet_regsql工具會(huì)在MSPetShop4數(shù)據(jù)庫(kù)中建立一個(gè)名為AspNet_SqlCacheTablesForChangeNotification的新數(shù)據(jù)庫(kù)表。該數(shù)據(jù)表包含三個(gè)字段。字段tableName記錄要追蹤的數(shù)據(jù)表的名稱,例如在PetShop 4.0中,要記錄的數(shù)據(jù)表就包括Category、Ite
49、m和Product。notificationCreated字段記錄開(kāi)始追蹤的時(shí)間。changeId作為一個(gè)類型為int的字段,用于記錄數(shù)據(jù)表數(shù)據(jù)發(fā)生變化的次數(shù)。如圖4-2所示:圖4-2 AspNet_SqlCacheTablesForChangeNotification數(shù)據(jù)表除此之外,執(zhí)行該命令還會(huì)為MSPetShop4數(shù)據(jù)庫(kù)添加一組存儲(chǔ)過(guò)程,為ASP.NET提供查詢追蹤的數(shù)據(jù)表的情況,同時(shí)還將為使用了SqlCacheDependency的表添加觸發(fā)器,分別對(duì)應(yīng)Insert、Update、Delete等與數(shù)據(jù)更改相關(guān)的操作。例如Product數(shù)據(jù)表的觸發(fā)器:Create TRIGGER dbo
50、.Product_AspNet_SqlCacheNotification_Trigger ON Product FOR Insert, Update, Delete AS BEGIN SET NOCOUNT ON EXEC dbo.AspNet_SqlCacheUpdateChangeIdStoredProcedure NProductEND其中,AspNet_SqlCacheUpdateChangeIdStoredProcedure即是工具添加的一組存儲(chǔ)過(guò)程中的一個(gè)。當(dāng)對(duì)Product數(shù)據(jù)表執(zhí)行Insert、Update或Delete等操作時(shí),就會(huì)激活觸發(fā)器,然后執(zhí)行AspNet_SqlCa
51、cheUpdateChangeIdStoredProcedure存儲(chǔ)過(guò)程。其執(zhí)行的過(guò)程就是修改AspNet_SqlCacheTablesForChangeNotification數(shù)據(jù)表的changeId字段值:Create PROCEDURE dbo.AspNet_SqlCacheUpdateChangeIdStoredProcedure tableName NVARCHAR(450) AS BEGIN Update dbo.AspNet_SqlCacheTablesForChangeNotification WITH (ROWLOCK) SET changeId = changeId + 1
52、 Where tableName = tableName ENDGO利用SqlCacheDependencyAdmin類我們也可以利用編程的方式來(lái)來(lái)管理數(shù)據(jù)庫(kù)對(duì)SqlCacheDependency特性的使用。該類包含了五個(gè)重要的方法:DisableNotifications為特定數(shù)據(jù)庫(kù)禁用 SqlCacheDependency對(duì)象更改通知DisableTableForNotifications為數(shù)據(jù)庫(kù)中的特定表禁用SqlCacheDependency對(duì)象更改通知EnableNotifications為特定數(shù)據(jù)庫(kù)啟用SqlCacheDependency對(duì)象更改通知EnableTableForNo
53、tifications為數(shù)據(jù)庫(kù)中的特定表啟用SqlCacheDependency對(duì)象更改通知GetTablesEnabledForNotifications返回啟用了SqlCacheDependency對(duì)象更改通知的所有表的列表表4-1 SqlCacheDependencyAdmin類的主要方法假設(shè)我們定義了如下的數(shù)據(jù)庫(kù)連接字符串:const string connectionStr = Server=localhost;Database=MSPetShop4;那么為數(shù)據(jù)庫(kù)MSPetShop4啟用SqlCacheDependency對(duì)象更改通知的實(shí)現(xiàn)為:protected void Page_
54、Load(object sender, EventArgs e) if (!IsPostBack) SqlCacheDependencyAdmin.EnableNotifications(connectionStr); 為數(shù)據(jù)表Product啟用SqlCacheDependency對(duì)象更改通知的實(shí)現(xiàn)則為:SqlCacheDependencyAdmin.EnableTableForNotifications(connectionStr, Product);如果要調(diào)用表4-1中所示的相關(guān)方法,需要注意的是訪問(wèn)SQL Server數(shù)據(jù)庫(kù)的帳戶必須具有創(chuàng)建表和存儲(chǔ)過(guò)程的權(quán)限。如果要調(diào)用EnableTa
55、bleForNotifications方法,還需要具有在該表上創(chuàng)建SQL Server觸發(fā)器的權(quán)限。雖然說(shuō)編程方式賦予了程序員更大的靈活性,但aspnet_regsql工具卻提供了更簡(jiǎn)單的方法實(shí)現(xiàn)對(duì)SqlCacheDependency的配置與管理。PetShop 4.0采用的正是aspnet_regsql工具的辦法,它編寫(xiě)了一個(gè)文件名為InstallDatabases d的批處理文件,其中包含了對(duì)aspnet_regsql工具的執(zhí)行,并通過(guò)安裝程序去調(diào)用該文件,實(shí)現(xiàn)對(duì)SQL Server的配置。PetShop作為一個(gè)B2C的寵物網(wǎng)上商店,需要充分考慮訪客的用戶體驗(yàn),如果因?yàn)閿?shù)據(jù)量大而導(dǎo)致Web
56、服務(wù)器的響應(yīng)不及時(shí),頁(yè)面和查詢數(shù)據(jù)遲遲得不到結(jié)果,會(huì)因此而破壞客戶訪問(wèn)網(wǎng)站的心情,在耗盡耐心的等待后,可能會(huì)失去這一部分客戶。無(wú)疑,這是非常糟糕的結(jié)果。因而在對(duì)其進(jìn)行體系架構(gòu)設(shè)計(jì)時(shí),整個(gè)系統(tǒng)的性能就顯得殊為重要。然而,我們不能因噎廢食,因?yàn)閷W⒂谛阅芏雎詳?shù)據(jù)的正確性。在PetShop 3.0版本以及之前的版本,因?yàn)锳SP.NET緩存的局限性,這一問(wèn)題并沒(méi)有得到很好的解決。PetShop 4.0則引入了SqlCacheDependency特性,使得系統(tǒng)對(duì)緩存的處理較之以前大為改觀。CacheDependency接口PetShop 4.0引入了SqlCacheDependency特性,對(duì)Cate
57、gory、Product和Item數(shù)據(jù)表對(duì)應(yīng)的緩存實(shí)施了SQL Cache Invalidation技術(shù)。當(dāng)對(duì)應(yīng)的數(shù)據(jù)表數(shù)據(jù)發(fā)生更改后,該技術(shù)能夠?qū)⑾嚓P(guān)項(xiàng)從緩存中移除。實(shí)現(xiàn)這一技術(shù)的核心是SqlCacheDependency類,它繼承了CacheDependency類。然而為了保證整個(gè)架構(gòu)的可擴(kuò)展性,我們也允許設(shè)計(jì)者建立自定義的CacheDependency類,用以擴(kuò)展緩存依賴。這就有必要為CacheDependency建立抽象接口,并在web.config文件中進(jìn)行配置。AggregateCacheDependency是.Net Framework 2.0新增的一個(gè)類,它負(fù)責(zé)監(jiān)視依賴項(xiàng)對(duì)象的
58、集合。當(dāng)這個(gè)集合中的任意一個(gè)依賴項(xiàng)對(duì)象發(fā)生改變時(shí),該依賴項(xiàng)對(duì)象對(duì)應(yīng)的緩存對(duì)象都將被自動(dòng)移除。AggregateCacheDependency類起到了組合CacheDependency對(duì)象的作用,它可以將多個(gè)CacheDependency對(duì)象甚至于不同類型的CacheDependency對(duì)象與緩存項(xiàng)建立關(guān)聯(lián)。由于PetShop需要為Category、Product和Item數(shù)據(jù)表建立依賴項(xiàng),因而IPetShopCacheDependency的接口方法GetDependency()其目的就是返回建立了這些依賴項(xiàng)的AggregateCacheDependency對(duì)象。CacheDependency實(shí)
59、現(xiàn)CacheDependency的實(shí)現(xiàn)正是為Category、Product和Item數(shù)據(jù)表建立了對(duì)應(yīng)的SqlCacheDependency類型的依賴項(xiàng),如代碼所示:public abstract class TableDependency : IPetShopCacheDependency / This is the separator thats used in web.config protected char configurationSeparator = new char , ; protected AggregateCacheDependency dependency = new
60、 AggregateCacheDependency(); protected TableDependency(string configKey) string dbName = ConfigurationManager.AppSettingsCacheDatabaseName; string tableConfig = ConfigurationManager.AppSettingsconfigKey; string tables = tableConfig.Split(configurationSeparator); foreach (string tableName in tables)
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 現(xiàn)代醫(yī)療用品的冷鏈物流管理策略
- 現(xiàn)代農(nóng)業(yè)技術(shù)推廣與農(nóng)業(yè)可持續(xù)發(fā)展
- 媽媽班活動(dòng)方案國(guó)慶節(jié)
- 2023八年級(jí)物理上冊(cè) 第二章 物質(zhì)世界的尺度、質(zhì)量和密度第二節(jié) 物體的質(zhì)量及其測(cè)量說(shuō)課稿 (新版)北師大版
- 4《同學(xué)相伴》第一課時(shí) 說(shuō)課稿-2023-2024學(xué)年道德與法治三年級(jí)下冊(cè)統(tǒng)編版
- 《6~9的加減法-用減法解決問(wèn)題》說(shuō)課稿-2024-2025學(xué)年一年級(jí)上冊(cè)數(shù)學(xué)人教版001
- 1少讓父母為我擔(dān)心(說(shuō)課稿)-統(tǒng)編版(五四制)道德與法治四年級(jí)上冊(cè)
- 2024-2025學(xué)年高中物理 第四章 勻速圓周運(yùn)動(dòng) 第3節(jié) 向心力的實(shí)例分析說(shuō)課稿 魯科版必修2
- Unit3《It's a colourful world!》(說(shuō)課稿)-2024-2025學(xué)年外研版(三起)(2024)英語(yǔ)三年級(jí)上冊(cè)(2課時(shí))
- Unit 4 I have a pen pal Part B Let's learn(說(shuō)課稿)-2023-2024學(xué)年人教PEP版英語(yǔ)六年級(jí)上冊(cè)
- 【課件】2024-2025學(xué)年高一上學(xué)期英語(yǔ)開(kāi)學(xué)第一課課件
- 年度重點(diǎn)工作計(jì)劃
- 《經(jīng)濟(jì)思想史》全套教學(xué)課件
- 環(huán)境衛(wèi)生學(xué)及消毒滅菌效果監(jiān)測(cè)
- 對(duì)合同條款有異議函
- 模板工程風(fēng)險(xiǎn)辨識(shí)及防范措施
- 中醫(yī)館工作細(xì)則
- 2024版《安全生產(chǎn)法》考試題庫(kù)附答案(共130題)
- 節(jié)后復(fù)工安全教育培訓(xùn)內(nèi)容【5篇】
- 尋夢(mèng)緣古法駐顏培訓(xùn)課件
- 員工招聘與人才引進(jìn)培訓(xùn)課件
評(píng)論
0/150
提交評(píng)論