PetShop 入門_第1頁
PetShop 入門_第2頁
PetShop 入門_第3頁
PetShop 入門_第4頁
PetShop 入門_第5頁
已閱讀5頁,還剩56頁未讀 繼續免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

1、一、PetShop的設計在軟件體系架構設計中,分層式結構是最常見,也是最重要的一種結構。微軟推薦的分層式結構一般分為三層,從下至上分別為:數據訪問層、業務邏輯層(又或成為領域層)、表示層,如圖所示:圖一:三層的分層式結構數據訪問層:有時候也稱為是持久層,其功能主要是負責數據庫的訪問。簡單的說法就是實現對數據表的Select,Insert,Update,Delete的操作。如果要加入ORM的元素,那么就會包括對象和數據表之間的mapping,以及對象實體的持久化。在PetShop的數據訪問層中,并沒有使用ORM,從而導致了代碼量的增加,可以看作是整個設計實現中的一大敗筆。業務邏輯層:是整個系統的

2、核心,它與這個系統的業務(領域)有關。以PetShop為例,業務邏輯層的相關設計,均和網上寵物店特有的邏輯相關,例如查詢寵物,下訂單,添加寵物到購物車等等。如果涉及到數據庫的訪問,則調用數據訪問層。表示層:是系統的UI部分,負責使用者與整個系統的交互。在這一層中,理想的狀態是不應包括系統的業務邏輯。表示層中的邏輯代碼,僅與界面元素有關。在PetShop中,是利用ASP.Net來設計的,因此包含了許多Web控件和相關邏輯。分層式結構究竟其優勢何在?Martin Fowler在Patterns of Enterprise Application Architecture一書中給出了答案:1、開發人

3、員可以只關注整個結構中的其中某一層;2、可以很容易的用新的實現來替換原有層次的實現;3、可以降低層與層之間的依賴;4、有利于標準化;5、利于各層邏輯的復用。概括來說,分層式設計可以達至如下目的:分散關注、松散耦合、邏輯復用、標準定義。一個好的分層式結構,可以使得開發人員的分工更加明確。一旦定義好各層次之間的接口,負責不同邏輯設計的開發人員就可以分散關注,齊頭并進。例如UI人員只需考慮用戶界面的體驗與操作,領域的設計人員可以僅關注業務邏輯的設計,而數據庫設計人員也不必為繁瑣的用戶交互而頭疼了。每個開發人員的任務得到了確認,開發進度就可以迅速的提高。松散耦合的好處是顯而易見的。如果一個系統沒有分層

4、,那么各自的邏輯都緊緊糾纏在一起,彼此間相互依賴,誰都是不可替換的。一旦發生改變,則牽一發而動全身,對項目的影響極為嚴重。降低層與層間的依賴性,既可以良好地保證未來的可擴展,在復用性上也是優勢明顯。每個功能模塊一旦定義好統一的接口,就可以被各個模塊所調用,而不用為相同的功能進行重復地開發。進行好的分層式結構設計,標準也是必不可少的。只有在一定程度的標準化基礎上,這個系統才是可擴展的,可替換的。而層與層之間的通信也必然保證了接口的標準化。“金無足赤,人無完人”,分層式結構也不可避免具有一些缺陷:1、降低了系統的性能。這是不言而喻的。如果不采用分層式結構,很多業務可以直接造訪數據庫,以此獲取相應的

5、數據,如今卻必須通過中間層來完成。2、有時會導致級聯的修改。這種修改尤其體現在自上而下的方向。如果在表示層中需要增加一個功能,為保證其設計符合分層式結構,可能需要在相應的業務邏輯層和數據訪問層中都增加相應的代碼。前面提到,PetShop的表示層是用ASP.Net設計的,也就是說,它應是一個BS系統。在.Net中,標準的BS分層式結構如下圖所示:圖二:.Net中標準的BS分層式結構隨著PetShop版本的更新,其分層式結構也在不斷的完善,例如PetShop2.0,就沒有采用標準的三層式結構,如圖三:圖三:PetShop 2.0的體系架構從圖中我們可以看到,并沒有明顯的數據訪問層設計。這樣的設計雖

6、然提高了數據訪問的性能,但也同時導致了業務邏輯層與數據訪問的職責混亂。一旦要求支持的數據庫發生變化,或者需要修改數據訪問的邏輯,由于沒有清晰的分層,會導致項目作大的修改。而隨著硬件系統性能的提高,以及充分利用緩存、異步處理等機制,分層式結構所帶來的性能影響幾乎可以忽略不計。PetShop3.0糾正了此前層次不明的問題,將數據訪問邏輯作為單獨的一層獨立出來:圖四:PetShop 3.0的體系架構PetShop5.0基本上延續了3.0的結構,但在性能上作了一定的改進,引入了緩存和異步處理機制,同時又充分利用了ASP.Net 2.0的新功能MemberShip,因此PetShop5.0的系統架構圖如

7、下所示:圖五:PetShop 5.0的體系架構比較3.0和5.0的系統架構圖,其核心的內容并沒有發生變化。在數據訪問層(DAL)中,仍然采用DAL Interface抽象出數據訪問邏輯,并以DAL Factory作為數據訪問層對象的工廠模塊。對于DAL Interface而言,分別有支持MS-SQL的SQL Server DAL和支持Oracle的Oracle DAL具體實現。而Model模塊則包含了數據實體對象。其詳細的模塊結構圖如下所示:圖六:數據訪問層的模塊結構圖可以看到,在數據訪問層中,完全采用了“面向接口編程”思想。抽象出來的IDAL模塊,脫離了與具體數據庫的依賴,從而使得整個數據訪

8、問層利于數據庫遷移。DALFactory模塊專門管理DAL對象的創建,便于業務邏輯層訪問。SQLServerDAL和OracleDAL模塊均實現IDAL模塊的接口,其中包含的邏輯就是對數據庫的Select,Insert,Update和Delete操作。因為數據庫類型的不同,對數據庫的操作也有所不同,代碼也會因此有所區別。此外,抽象出來的IDAL模塊,除了解除了向下的依賴之外,對于其上的業務邏輯層,同樣僅存在弱依賴關系,如下圖所示:圖七:業務邏輯層的模塊結構圖圖七中BLL是業務邏輯層的核心模塊,它包含了整個系統的核心業務。在業務邏輯層中,不能直接訪問數據庫,而必須通過數據訪問層。注意圖中對數據訪

9、問業務的調用,是通過接口模塊IDAL來完成的。既然與具體的數據訪問邏輯無關,則層與層之間的關系就是松散耦合的。如果此時需要修改數據訪問層的具體實現,只要不涉及到IDAL的接口定義,那么業務邏輯層就不會受到任何影響。畢竟,具體實現的SQLServerDAL和OracalDAL根本就與業務邏輯層沒有半點關系。因為在PetShop 5.0中引入了異步處理機制。插入訂單的策略可以分為同步和異步,兩者的插入策略明顯不同,但對于調用者而言,插入訂單的接口是完全一樣的,所以PetShop 5.0中設計了IBLLStrategy模塊。雖然在IBLLStrategy模塊中,僅僅是簡單的IOrderStategy

10、,但同時也給出了一個范例和信息,那就是在業務邏輯的處理中,如果存在業務操作的多樣化,或者是今后可能的變化,均應利用抽象的原理。或者使用接口,或者使用抽象類,從而脫離對具體業務的依賴。不過在PetShop中,由于業務邏輯相對簡單,這種思想體現得不夠明顯。也正因為此,PetShop將核心的業務邏輯都放到了一個模塊BLL中,并沒有將具體的實現和抽象嚴格的按照模塊分開。所以表示層和業務邏輯層之間的調用關系,其耦合度相對較高:圖八:表示層的模塊結構圖在圖五中,各個層次中還引入了輔助的模塊,如數據訪問層的Messaging模塊,是為異步插入訂單的功能提供,采用了MSMQ(Microsoft Messagi

11、ng Queue)技術。而表示層的CacheDependency則提供緩存功能。這些特殊的模塊,我會在此后的文章中詳細介紹。PetShop5.0 詳解之二(數據訪問層之數據庫訪問設計) 在系列一中,我從整體上分析了PetShop的架構設計,并提及了分層的概念。從本部分開始,我將依次對各層進行代碼級的分析,以求獲得更加細致而深入的理解。在PetShop 5.0中,由于引入了ASP.Net 2.0的一些新特色,所以數據層的內容也更加的廣泛和復雜,包括:數據庫訪問、Messaging、MemberShip、Profile四部分。在系列二中,我將介紹有關數據庫訪問的設計。在PetShop中,系統需要處

12、理的數據庫對象分為兩類:一是數據實體,對應數據庫中相應的數據表。它們沒有行為,僅用于表現對象的數據。這些實體類都被放到Model程序集中,例如數據表Order對應的實體類OrderInfo,其類圖如下:這些對象并不具有持久化的功能,簡單地說,它們是作為數據的載體,便于業務邏輯針對相應數據表進行讀/寫操作。雖然這些類的屬性分別映射了數據表的列,而每一個對象實例也恰恰對應于數據表的每一行,但這些實體類卻并不具備對應的數據庫訪問能力。由于數據訪問層和業務邏輯層都將對這些數據實體進行操作,因此程序集Model會被這兩層的模塊所引用。第二類數據庫對象則是數據的業務邏輯對象。這里所指的業務邏輯,并非業務邏

13、輯層意義上的領域(domain)業務邏輯(從這個意義上,我更傾向于將業務邏輯層稱為“領域邏輯層”),一般意義上說,這些業務邏輯即為基本的數據庫操作,包括Select,Insert,Update和Delete。由于這些業務邏輯對象,僅具有行為而與數據無關,因此它們均被抽象為一個單獨的接口模塊IDAL,例如數據表Order對應的接口IOrder:將數據實體與相關的數據庫操作分離出來,符合面向對象的精神。首先,它體現了“職責分離”的原則。將數據實體與其行為分開,使得兩者之間依賴減弱,當數據行為發生改變時,并不影響Model模塊中的數據實體對象,避免了因一個類職責過多、過大,從而導致該類的引用者發生“

14、災難性”的影響。其次,它體現了“抽象”的精神,或者說是“面向接口編程”的最佳體現。抽象的接口模塊IDAL,與具體的數據庫訪問實現完全隔離。這種與實現無關的設計,保證了系統的可擴展性,同時也保證了數據庫的可移植性。在PetShop中,可以支持SQL Server和Oracle,那么它們具體的實現就分別放在兩個不同的模塊SQLServerDAL、OracleDAL中。以Order為例,在SQLServerDAL、OracleDAL兩個模塊中,有不同的實現,但它們同時又都實現了IOrder接口,如圖:從數據庫的實現來看,PetShop體現出了沒有ORM框架的臃腫與丑陋。由于要對數據表進行Insert

15、和Select操作,以SQL Server為例,就使用了SqlCommand,SqlParameter,SqlDataReader等對象,以完成這些操作。尤其復雜的是Parameter的傳遞,在PetShop中,使用了大量的字符串常量來保存參數的名稱。此外,PetShop還專門為SQL Server和Oracle提供了抽象的Helper類,包裝了一些常用的操作,如ExecuteNonQuery、ExecuteReader等方法。在沒有ORM的情況下,使用Helper類是一個比較好的策略,利用它來完成數據庫基本操作的封裝,可以減少很多和數據庫操作有關的代碼,這體現了對象復用的原則。PetShop

16、將這些Helper類統一放到DBUtility模塊中,不同數據庫的Helper類暴露的方法基本相同,只除了一些特殊的要求,例如Oracle中處理bool類型的方式就和SQL Server不同,從而專門提供了OraBit和OraBool方法。此外,Helper類中的方法均為static方法,以利于調用。OracleHelper的類圖如下:對于數據訪問層來說,最頭疼的是SQL語句的處理。在早期的CS結構中,由于未采用三層式架構設計,數據訪問層和業務邏輯層是緊密糅合在一起的,因此,SQL語句遍布與系統的每一個角落。這給程序的維護帶來極大的困難。此外,由于Oracle使用的是PL-SQL,而SQL S

17、erver和Sybase等使用的是T-SQL,兩者雖然都遵循了標準SQL的語法,但在很多細節上仍有區別,如果將SQL語句大量的使用到程序中,無疑為可能的數據庫移植也帶來了困難。最好的方法是采用存儲過程。這種方法使得程序更加整潔,此外,由于存儲過程可以以數據庫腳本的形式存在,也便于移植和修改。但這種方式仍然有缺陷。一是存儲過程的測試相對困難。雖然有相應的調試工具,但比起對代碼的調試而言,仍然比較復雜且不方便。二是對系統的更新帶來障礙。如果數據庫訪問是由程序完成,在.Net平臺下,我們僅需要在修改程序后,將重新編譯的程序集xcopy到部署的服務器上即可。如果使用了存儲過程,出于安全的考慮,必須有專

18、門的DBA重新運行存儲過程的腳本,部署的方式受到了限制。我曾經在一個項目中,利用一個專門的表來存放SQL語句。如要使用相關的SQL語句,就利用關鍵字搜索獲得對應語句。這種做法近似于存儲過程的調用,但卻避免了部署上的問題。然而這種方式卻在性能上無法得到保證。它僅適合于SQL語句較少的場景。不過,利用良好的設計,我們可以為各種業務提供不同的表來存放SQL語句。同樣的道理,這些SQL語句也可以存放到XML文件中,更有利于系統的擴展或修改。不過前提是,我們需要為它提供專門的SQL語句管理工具。SQL語句的使用無法避免,如何更好的應用SQL語句也無定論,但有一個原則值得我們遵守,就是“應該盡量讓SQL語

19、句盡存在于數據訪問層的具體實現中”。當然,如果應用ORM,那么一切就變得不同了。因為ORM框架已經為數據訪問提供了基本的Select,Insert,Update和Delete操作了。例如在NHibernate中,我們可以直接調用ISession對象的Save方法,來Insert(或者說是Create)一個數據實體對象:public void Insert(OrderInfo order) ISession s = Sessions.GetSession(); ITransaction trans = null; try trans = s.BeginTransaction(); s.Save(

20、 order); trans.Commit(); finally s.Close(); 沒有SQL語句,也沒有那些煩人的Parameters,甚至不需要專門去考慮事務。此外,這樣的設計,也是與數據庫無關的,NHibernate可以通過Dialect(方言)的機制支持不同的數據庫。唯一要做的是,我們需要為OrderInfo定義hbm文件。當然,ORM框架并非是萬能的,面對紛繁復雜的業務邏輯,它并不能完全消滅SQL語句,以及替代復雜的數據庫訪問邏輯,但它卻很好的體現了“80/20(或90/10)法則”(也被稱為“帕累托法則”),也就是說:花比較少(10%-20%)的力氣就可以解決大部分(80%-9

21、0%)的問題,而要解決剩下的少部分問題則需要多得多的努力。至少,那些在數據訪問層中占據了絕大部分的CRUD操作,通過利用ORM框架,我們就僅需要付出極少數時間和精力來解決它們了。這無疑縮短了整個項目開發的周期。還是回到對PetShop的討論上來。現在我們已經有了數據實體,數據對象的抽象接口和實現,可以說有關數據庫訪問的主體就已經完成了。留待我們的還有兩個問題需要解決:1、數據對象創建的管理2、利于數據庫的移植在PetShop中,要創建的數據對象包括Order,Product,Category,Inventory,Item。在前面的設計中,這些對象已經被抽象為對應的接口,而其實現則根據數據庫的不

22、同而有所不同。也就是說,創建的對象有多種類別,而每種類別又有不同的實現,這是典型的抽象工廠模式的應用場景。而上面所述的兩個問題,也都可以通過抽象工廠模式來解決。標準的抽象工廠模式類圖如下:例如,創建SQL Server的Order對象如下:PetShopFactory factory = new SQLServerFactory();IOrder = factory.CreateOrder();要考慮到數據庫的可移植性,則factory必須作為一個全局變量,并在主程序運行時被實例化。但這樣的設計雖然已經達到了“封裝變化”的目的,但在創建PetShopFactory對象時,仍不可避免的出現了具體

23、的類SQLServerFactory,也即是說,程序在這個層面上產生了與SQLServerFactory的強依賴。一旦整個系統要求支持Oracle,那么還需要修改這行代碼為:PetShopFactory factory = new oracleFactory();修改代碼的這種行為顯然是不可接受的。解決的辦法是“依賴注入”。“依賴注入”的功能通常是用專門的IoC容器提供的,在Java平臺下,這樣的容器包括Spring,PicoContainer等。而在.Net平臺下,最常見的則是Spring.Net。不過,在PetShop系統中,并不需要專門的容器來實現“依賴注入”,簡單的做法還是利用配置文件

24、和反射功能來實現。也就是說,我們可以在web.config文件中,配置好具體的Factory對象的完整的類名。然而,當我們利用配置文件和反射功能時,具體工廠的創建就顯得有些“畫蛇添足”了,我們完全可以在配置文件中,直接指向具體的數據庫對象實現類,例如PetShop.SQLServerDAL.IOrder。那么,抽象工廠模式中的相關工廠就可以簡化為一個工廠類了,所以我將這種模式稱之為“具有簡單工廠特質的抽象工廠模式”,其類圖如下:DataAccess類完全取代了前面創建的工廠類體系,它是一個sealed類,其中創建各種數據對象的方法,均為靜態方法。之所以能用這個類達到抽象工廠的目的,是因為配置文

25、件和反射的運用,如下的代碼片斷所示:public sealed class DataAccess/ Look up the DAL implementation we should be using private static readonly string path = ConfigurationManager.AppSettings”WebDAL”; private static readonly string orderPath = ConfigurationManager.AppSettings”OrdersDAL”;public static PetShop.IDAL.IOrder

26、 CreateOrder() string className = orderPath + “.Order”; return (PetShop.IDAL.IOrder)Assembly.Load(orderPath).CreateInstance(className); 在PetShop中,這種依賴配置文件和反射創建對象的方式極其常見,包括IBLLStategy、CacheDependencyFactory等等。這些實現邏輯散布于整個PetShop系統中,在我看來,是可以在此基礎上進行重構的。也就是說,我們可以為整個系統提供類似于“Service Locator”的實現:public stat

27、ic class ServiceLocatorprivate static readonly string dalPath = ConfigurationManager.AppSettings”WebDAL”; private static readonly string orderPath = ConfigurationManager.AppSettings”OrdersDAL”;/private static readonly string orderStategyPath = ConfigurationManager.AppSettings”OrderStrategyAssembly”;

28、public static object LocateDALObject(string className)string fullPath = dalPath + “.” + className;return Assembly.Load(dalPath).CreateInstance(fullPath);public static object LocateDALOrderObject(string className)string fullPath = orderPath + “.” + className;return Assembly.Load(orderPath).CreateInst

29、ance(fullPath);public static object LocateOrderStrategyObject(string className)string fullPath = orderStategyPath + “.” + className;return Assembly.Load(orderStategyPath).CreateInstance(fullPath);/那么和所謂“依賴注入”相關的代碼都可以利用ServiceLocator來完成。例如類DataAccess就可以簡化為:public sealed class DataAccesspublic static

30、PetShop.IDAL.IOrder CreateOrder() return (PetShop.IDAL.IOrder)ServiceLocator. LocateDALOrderObject(”Order”); 通過ServiceLocator,將所有與配置文件相關的namespace值統一管理起來,這有利于各種動態創建對象的管理和未來的維護。Trackback: PetShop5.0 詳解之三(PetShop數據訪問層之消息處理)在進行系統設計時,除了對安全、事務等問題給與足夠的重視外,性能也是一個不可避免的問題所在,尤其是一個B/S結構的軟件系統,必須充分地考慮訪問量、數據流量、服務

31、器負荷的問題。解決性能的瓶頸,除了對硬件系統進行升級外,軟件設計的合理性尤為重要。在前面我曾提到,分層式結構設計可能會在一定程度上影響數據訪問的性能,然而與它給設計人員帶來的好處相比,幾乎可以忽略。要提供整個系統的性能,還可以從數據庫的優化著手,例如連接池的使用、建立索引、優化查詢策略等等,例如在PetShop中就利用了數據庫的Cache,對于數據量較大的訂單數據,則利用分庫的方式為其單獨建立了Order和Inventory數據庫。而在軟件設計上,比較有用的方式是利用多線程與異步處理方式。在PetShop5.0中,使用了Microsoft Messaging Queue(MSMQ)技術來完成異

32、步處理,利用消息隊列臨時存放要插入的數據,使得數據訪問因為不需要訪問數據庫從而提供了訪問性能,至于隊列中的數據,則等待系統空閑的時候再進行處理,將其最終插入到數據庫中。PetShop5.0中的消息處理,主要分為如下幾部分:消息接口IMessaging、消息工廠MessagingFactory、MSMQ實現MSMQMessaging以及數據后臺處理應用程序OrderProcessor。從模塊化分上,PetShop自始自終地履行了“面向接口設計”的原則,將消息處理的接口與實現分開,并通過工廠模式封裝消息實現對象的創建,以達到松散耦合的目的。由于在PetShop中僅對訂單的處理使用了異步處理方式,因

33、此在消息接口IMessaging中,僅定義了一個IOrder接口,其類圖如下:在對消息接口的實現中,考慮到未來的擴展中會有其他的數據對象會使用MSMQ,因此定義了一個Queue的基類,實現消息Receive和Send的基本操作:public virtual object Receive() try using (Message message = queue.Receive(timeout, transactionType) return message; catch (MessageQueueException mqex) if (mqex.MessageQueueErrorCode = M

34、essageQueueErrorCode.IOTimeout) throw new TimeoutException(); throw; public virtual void Send(object msg) queue.Send(msg, transactionType);其中queue對象是System.Messaging.MessageQueue類型,作為存放數據的隊列。MSMQ隊列是一個可持久的隊列,因此不必擔心用戶不間斷地下訂單會導致訂單數據的丟失。在PetShopQueue設置了timeout值,OrderProcessor會根據timeout值定期掃描隊列中的訂單數據。MSMQ

35、Messaging模塊中,Order對象實現了IMessaging模塊中定義的接口IOrder,同時它還繼承了基類PetShopQueue,其定義如下:public class order:PetShopQueue, PetShop.IMessaging.IOrder方法的實現代碼如下: public new orderInfo Receive() / This method involves in distributed transaction and need Automatic Transaction type base.transactionType = MessageQueueTra

36、nsactionType.Automatic; return (OrderInfo)(Message)base.Receive().Body; public orderInfo Receive(int timeout) base.timeout = TimeSpan.FromSeconds(Convert.ToDouble(timeout); return Receive(); public void Send(OrderInfo orderMessage) / This method does not involve in distributed transaction and optimi

37、zes performance using Single type base.transactionType = MessageQueueTransactionType.Single; base.Send(orderMessage); 所以,最后的類圖應該如下:注意在Order類的Receive()方法中,是用new關鍵字而不是override關鍵字來重寫其父類PetShopQueue的Receive()虛方法。因此,如果是實例化如下的對象,將會調用PetShopQueue的Receive()方法,而不是子類Order的Receive()方法:PetShopQueue queue = new

38、order();queue.Receive();從設計上來看,由于PetShop采用“面向接口設計”的原則,如果我們要創建Order對象,應該采用如下的方式:IOrder order = new order();order.Receive();考慮到IOrder的實現有可能的變化,PetShop仍然利用了工廠模式,將IOrder對象的創建用專門的工廠模塊進行了封裝:在類QueueAccess中,通過CreateOrder()方法利用反射技術創建正確的IOrder類型對象: public static PetShop.IMessaging.IOrder CreateOrder() string

39、className = path + .Order; return PetShop.IMessaging.IOrder)Assembly.Load(path).CreateInstance(className); path的值通過配置文件獲取:private static readonly string path = ConfigurationManager.AppSettingsOrderMessaging;而配置文件中,OrderMessaging的值設置如下:之所以利用工廠模式來負責對象的創建,是便于在業務層中對其調用,例如在BLL模塊中OrderAsynchronous類:public

40、 class orderAsynchronous : IOrderStrategy private static readonly PetShop.IMessaging.IOrder asynchOrder = PetShop.MessagingFactory.QueueAccess.CreateOrder(); public void Insert(PetShop.Model.OrderInfo order) asynchOrder.Send(order); 一旦IOrder接口的實現發生變化,這種實現方式就可以使得客戶僅需要修改配置文件,而不需要修改代碼,如此就可以避免程序集的重新編譯和部

41、署,使得系統能夠靈活應對需求的改變。例如定義一個實現IOrder接口的SpecialOrder,則可以新增一個模塊,如PetShop.SpecialMSMQMessaging,而類名則仍然為Order,那么此時我們僅需要修改配置文件中OrderMessaging的值即可:OrderProcessor是一個控制臺應用程序,不過可以根據需求將其設計為Windows Service。它的目的就是接收消息隊列中的訂單數據,然后將其插入到Order和Inventory數據庫中。它利用了多線程技術,以達到提高系統性能的目的。在OrderProcessor應用程序中,主函數Main用于控制線程,而核心的執行

42、任務則由方法ProcessOrders()實現: private static void ProcessOrders() / the transaction timeout should be long enough to handle all of orders in the batch TimeSpan tsTimeout = TimeSpan.FromSeconds(Convert.ToDouble(transactionTimeout * batchSize); order order = new order(); while (true) / queue timeout variab

43、les TimeSpan datetimeStarting = new TimeSpan(DateTime.Now.Ticks); double elapsedTime = 0; int processedItems = 0; ArrayList queueOrders = new ArrayList(); using (TransactionScope ts = new TransactionScope(TransactionScopeOption.Required, tsTimeout) / Receive the orders from the queue for (int j = 0;

44、 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 /update elapsed time elapsedTime = new TimeSpan(DateTime.N

45、ow.Ticks).TotalSeconds - datetimeStarting.TotalSeconds; catch (TimeoutException) /exit loop because no more messages are waiting j = batchSize; /process the queued orders for (int k = 0; k queueOrders.Count; k+) order.Insert(OrderInfo)queueOrdersk); processedItems+; totalOrdersProcessed+; /batch com

46、plete or MSMQ receive timed out ts.Complete(); Console.WriteLine(Thread Id + Thread.CurrentThread.ManagedThreadId + ) batch finished, + processedItems + items, in + elapsedTime.ToString() + seconds.); 首先,它會通過PetShop.BLL.Order類的公共方法ReceiveFromQueue()來獲取消息隊列中的訂單數據,并將其放入到一個ArrayList對象中,然而再調用PetShop.BLL

47、.Order類的Insert方法將其插入到Order和Inventory數據庫中。在PetShop.BLL.Order類中,并不是直接執行插入訂單的操作,而是調用了IOrderStrategy接口的Insert()方法:public void Insert(OrderInfo order) / Call credit card procesor ProcessCreditCard(order); / Insert the order (a)synchrounously based on configuration orderInsertStrategy.Insert(order);在這里,運用

48、了一個策略模式,類圖如下所示:在PetShop.BLL.Order類中,仍然利用配置文件來動態創建IOrderStategy對象:private static readonly PetShop.IBLLStrategy.IOrderStrategy orderInsertStrategy = LoadInsertStrategy();private static PetShop.IBLLStrategy.IOrderStrategy LoadInsertStrategy() / Look up which strategy to use from config file string path

49、 = ConfigurationManager.AppSettingsOrderStrategyAssembly; string className = ConfigurationManager.AppSettingsOrderStrategyClass; / Using the evidence given in the config file load the appropriate assembly and class return (PetShop.IBLLStrategy.IOrderStrategy)Assembly.Load(path).CreateInstance(classN

50、ame);由于OrderProcessor是一個單獨的應用程序,因此它使用的配置文件與PetShop不同,是存放在應用程序的App.config文件中,在該文件中,對IOrderStategy的配置為:因此,以異步方式插入訂單的流程如下圖所示:Microsoft Messaging Queue(MSMQ)技術除用于異步處理以外,它主要還是一種分布式處理技術。分布式處理中,一個重要的技術要素就是有關消息的處理,而在System.Messaging命名空間中,已經提供了Message類,可以用于承載消息的傳遞,前提上消息的發送方與接收方在數據定義上應有統一的接口規范。MSMQ在分布式處理的運用,在

51、我參與的項目中已經有了實現。在為一個汽車制造商開發一個大型系統時,分銷商Dealer作為.Net客戶端,需要將數據傳遞到管理中心,并且該數據將被Oracle的EBS(E-Business System)使用。由于分銷商管理系統(DMS)采用的是C/S結構,數據庫為SQL Server,而汽車制造商管理中心的EBS數據庫為Oracle。這里就涉及到兩個系統之間數據的傳遞。實現架構如下: 首先Dealer的數據通過MSMQ傳遞到MSMQ Server,此時可以將數據插入到SQL Server數據庫中,同時利用FTP將數據傳送到專門的文件服務器上。然后利用IBM的EAI技術(企業應用集成,Enter

52、prise Application Itegration)定期將文件服務器中的文件,利用接口規范寫入到EAI數據庫服務器中,并最終寫道EBS的Oracle數據庫中。上述架構是一個典型的分布式處理結構,而技術實現的核心就是MSMQ和EAI。由于我們已經定義了統一的接口規范,在通過消息隊列形成文件后,此時的數據就已經與平臺無關了,使得在.Net平臺下的分銷商管理系統能夠與Oracle的EBS集成起來,完成數據的處理。PetShop5.0 詳解之四(PetShop之ASP.NET緩存)如果對微型計算機硬件系統有足夠的了解,那么我們對于Cache這個名詞一定是耳熟能詳的。在CPU以及主板的芯片中,都引入了這種名為高速緩沖存儲器(Cache)的技術。因為Cache的存取速度比內存快,因而引入Cache能夠有效的解決CPU與內存之間的速度不匹配問題。硬件系統可以利用Cache存儲CPU訪問概率高的那些數據,當CPU需要訪問這些數據時,可以直接從Cache中讀取,而不必訪問存取速度相對較慢的內存,從而提高了CPU的工作效率。軟件設計借鑒了硬件設計中引入緩存的

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論