小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

博客園 - 春魚編程觀點(diǎn) - 數(shù)據(jù)與操作的分離、數(shù)據(jù)實(shí)體設(shè)計(jì)及零、一與多(單體與集合)的辨證統(tǒng)一

 liuqg 2006-03-09
 
春魚 2004-09-10

摘要

本文著重論述了在 .NET 平臺(tái)進(jìn)行應(yīng)用程序開發(fā)時(shí)數(shù)據(jù)實(shí)體(entities)的設(shè)計(jì),對(duì)象型實(shí)體與結(jié)構(gòu)型實(shí)體的統(tǒng)一,以及由此引出的更深層次的對(duì)于應(yīng)用系統(tǒng)設(shè)計(jì)理念的思考。

本文的重點(diǎn)是如何將“結(jié)構(gòu)型”實(shí)體和“對(duì)象型”實(shí)體相互結(jié)合。而不是僅僅論述DataSet用作數(shù)據(jù)實(shí)體。

引言

設(shè)計(jì)一個(gè)“多層”應(yīng)用系統(tǒng)時(shí),一個(gè)必須考慮的關(guān)鍵問題就是如何在各層之間傳送數(shù)據(jù)。一個(gè)已經(jīng)成型的做法是設(shè)計(jì)不同規(guī)格的類來反映真實(shí)世界的業(yè)務(wù)對(duì)象。這些類往往包含常規(guī)數(shù)據(jù)類型、數(shù)列、集合或者記錄集。把這些數(shù)據(jù)組合起來,就可以用來在各層的調(diào)用之間保持業(yè)務(wù)數(shù)據(jù)。 這些承載業(yè)務(wù)數(shù)據(jù)的對(duì)象就是業(yè)務(wù)實(shí)體(entities)。

NET提供了DataSet類表現(xiàn)多個(gè)數(shù)據(jù)表以及他們之間的關(guān)系。當(dāng)我們向一個(gè)DataSet引入高級(jí)特性或者定義時(shí),一個(gè)強(qiáng)類型化的DataSet就成為數(shù)據(jù)實(shí)體的新的、先進(jìn)的選擇。

但是,真正將DataSet投入應(yīng)用時(shí),也許事情就沒有想象中那么簡(jiǎn)單了。很多朋友感言他們必須面對(duì)大量的編碼工作,還有的朋友認(rèn)為DataSet太有牽制性。

在應(yīng)用系統(tǒng)的設(shè)計(jì)中,數(shù)據(jù)實(shí)體一般被定義為存儲(chǔ)業(yè)務(wù)數(shù)據(jù)的一組類??梢詫I(yè)務(wù)實(shí)體設(shè)計(jì)為僅僅定義業(yè)務(wù)數(shù)據(jù),并不處理任何業(yè)務(wù)邏輯,實(shí)際上數(shù)據(jù)實(shí)體也最好設(shè)計(jì)成這樣。可以實(shí)現(xiàn)有效的邏輯隔離,提高內(nèi)聚性。這就是通常意義上所說的“結(jié)構(gòu)型”數(shù)據(jù)實(shí)體。

與結(jié)構(gòu)型數(shù)據(jù)實(shí)體相對(duì)的是“對(duì)象型”數(shù)據(jù)實(shí)體。對(duì)象型實(shí)體是傳統(tǒng)的實(shí)體設(shè)計(jì)模式。在這一模式中,業(yè)務(wù)數(shù)據(jù)以對(duì)象的方式表現(xiàn)。而這些對(duì)象一般是從Object派生而來的。我們必須給對(duì)象設(shè)計(jì)都有那些特性、行為。對(duì)象型實(shí)體可以很形象地表現(xiàn)業(yè)務(wù)模型,但不適合表現(xiàn)集合數(shù)據(jù)。另外對(duì)象型實(shí)體可以實(shí)現(xiàn)派生、繼承等特性。這是結(jié)構(gòu)型實(shí)體所欠缺的。

既然“對(duì)象型”和“結(jié)構(gòu)型”各有優(yōu)略,本文的作者就想到了是否可以將二者結(jié)合,起到互補(bǔ)的作用?經(jīng)過實(shí)踐,本文作者也獲得了一點(diǎn)小小的心得。特撰文同博友們分享。本文的觀點(diǎn)、思路可能是錯(cuò)誤的,權(quán)做批判之用。

DataSet用作數(shù)據(jù)實(shí)體優(yōu)劣勢(shì)分析

以作者的看法,DataSet適合用作實(shí)體在于:

1.天生可以表示多級(jí)的、邏輯結(jié)構(gòu)化的、集合的數(shù)據(jù)

2.適合被表示層(presentation layer)表現(xiàn)。眾所周知,DataSet很容易綁定到表示層的數(shù)據(jù)綁定控件

3.容易從后端活化/持久化(persistent),通過DataAdapter系列對(duì)象和一定的映射規(guī)則,可以以自由的方式實(shí)現(xiàn)與后端數(shù)據(jù)庫的數(shù)據(jù)交換

4.?dāng)?shù)據(jù)集中,做為參數(shù)傳遞時(shí)形式單一,管理與維護(hù)具有一致的外觀

5.適合對(duì)返回的數(shù)據(jù)集進(jìn)行二次處理,例如排序,篩選等

但是單純使用原生(raw)的DataSet時(shí)并不會(huì)帶來實(shí)際的好處。

第一,原始的DataSet數(shù)據(jù)定義并不固定,程序處理一個(gè)DataSet時(shí),并不能確定改對(duì)象中一定包含某表,某表中一定定義了某列。當(dāng)我們?cè)趂ill過程中出錯(cuò)時(shí),DataSet也許并沒有被格式化為預(yù)期的格式,這樣程序就會(huì)出錯(cuò)。而這個(gè)錯(cuò)誤在運(yùn)行期是無法避免的。

第二,非強(qiáng)類型化的對(duì)象要求我們必須以字符串形式訪問table和column,這樣就要求我們?cè)诔绦蛑袑?duì)這些table name和column name進(jìn)行硬編碼,這就帶來了問題,一方面我們必須以很大成本保證這些名稱的一致性,另一方面當(dāng)數(shù)據(jù)定義發(fā)生變動(dòng),我們又必須對(duì)程序作出相應(yīng)的改動(dòng)。牽一發(fā)而動(dòng)全身,這樣我們做“多層”,做“企業(yè)級(jí)”,實(shí)際上是給自己帶來了麻煩。

考慮以上因素,我們?cè)趹?yīng)用中定義一系列強(qiáng)類型化的DataSet做為在應(yīng)用級(jí)上做為承載業(yè)務(wù)數(shù)據(jù)的業(yè)務(wù)實(shí)體,我們需要詳細(xì)定義DataSet結(jié)構(gòu),包含那些表,表內(nèi)包含的列,表之間的關(guān)系或約束等。所作的工作等于重新定義了一套數(shù)據(jù)庫,這個(gè)內(nèi)存中的看不見摸不著的“數(shù)據(jù)庫”通過DataAdapter對(duì)象與后端真實(shí)的數(shù)據(jù)庫交換數(shù)據(jù),完成我們的業(yè)務(wù)操作。

兩種方法可以實(shí)現(xiàn)類型化的(strong-typed)DataSet:

1.使用DataSet.xsd定義

2.使用純編碼

當(dāng)我們依靠純編碼定義DataSet時(shí),我們必須在派生出一個(gè)DataSet對(duì)象,之后定義一系列常量,用來表示table name和column name。然后在對(duì)象的構(gòu)造階段(構(gòu)造器)中分別實(shí)例化各table對(duì)象,給table對(duì)象增加column, 所有這些完成后,我們就完成了一個(gè)強(qiáng)類型化的DataSet。

使用XSD定義DataSet可以免去編碼的“痛苦"階段,我們僅需要在設(shè)計(jì)期中增加表,列。甚至直接從Server Explorer中拖動(dòng)一個(gè)后端的表進(jìn)來,IDE可以為我們自動(dòng)生成XML。

這種類型化了的DataSet通常包含數(shù)個(gè)相關(guān)的“表”。每個(gè)數(shù)據(jù)實(shí)體包含那些表,而表的結(jié)構(gòu)是如何定義的(包含那些列,列的數(shù)據(jù)類型)都是確定了的。并且將表、列、表之間的關(guān)系都通過public property對(duì)外公開。這樣業(yè)務(wù)實(shí)體就像是一個(gè)內(nèi)部打好了格子的箱子,可以裝那些數(shù)據(jù)都規(guī)定好了,我們很清楚里面都有些什么,而數(shù)據(jù)是什么格式的也就很清楚了。

當(dāng)我們的業(yè)務(wù)模型變得足夠復(fù)雜,建模工作將會(huì)是一項(xiàng)challenging task。因?yàn)槲覀儽仨毧紤]到業(yè)務(wù)模型的適合性,由于各個(gè)業(yè)務(wù)層次都需要參考“標(biāo)準(zhǔn)的業(yè)務(wù)模型”,這涉及到業(yè)務(wù)實(shí)體在前端的綁定性能、在中間層的處理性能以及在后端的持久化、活化性能。所以業(yè)務(wù)模型的設(shè)計(jì)工作異常之關(guān)鍵,必須慎之又慎。

既然設(shè)計(jì)實(shí)體是如此之艱難,必有其可取之處。我們?yōu)槭裁匆ㄟ@么大成本設(shè)計(jì)數(shù)據(jù)實(shí)體呢?

這些就是使用數(shù)據(jù)實(shí)體的好處:

1.保持層次間數(shù)據(jù)交換結(jié)構(gòu)的統(tǒng)一
當(dāng)數(shù)據(jù)被類型化以后,所表示的數(shù)據(jù)類型就確定了下來。我們可以通過其public property訪問各表、行,而不用擔(dān)心會(huì)出現(xiàn)格式和定義錯(cuò)誤。

2.提高靈活性 當(dāng)我們修改了數(shù)據(jù)實(shí)體的定義時(shí),不用因?yàn)閿?shù)據(jù)的更改牽制到關(guān)鍵接口的更改。

3.減少出錯(cuò)的可能性 當(dāng)我們面對(duì)一類經(jīng)過定義的“透明”的實(shí)體時(shí),減少了將數(shù)據(jù)定義硬編碼在源代碼中,可降低出錯(cuò)的可能性。

4.可實(shí)現(xiàn)“類型化的綁定過程”:我們向特定的數(shù)據(jù)綁定控件(有可能也是類型化的)綁定類型化的結(jié)構(gòu)數(shù)據(jù)時(shí),綁定的過程是非常統(tǒng)一的。實(shí)際上我們只需要在一個(gè)統(tǒng)一環(huán)節(jié)中定義綁定的過程。而用到這種類型的綁定的情境中只要簡(jiǎn)單地使用一個(gè)命令就可以了。

5.可實(shí)現(xiàn)“類型化的持久化和活化”:這一提法實(shí)際上指的是業(yè)務(wù)實(shí)體與后端關(guān)系數(shù)據(jù)庫之間的映射。當(dāng)我們的業(yè)務(wù)系統(tǒng)設(shè)計(jì)得足夠好時(shí),我們可以定義業(yè)務(wù)實(shí)體和數(shù)據(jù)庫之間表、列之間的映射關(guān)系。這樣就可以把數(shù)據(jù)的活化和持久化、更新過程進(jìn)一步簡(jiǎn)化。甚至“寫刪改”等對(duì)數(shù)據(jù)的改動(dòng)操作都可以簡(jiǎn)化為單一的“Update”過程。

值得說明的是,以上僅僅是“類型化”DataSet所帶來的。到現(xiàn)在我們可以意識(shí)到,我們需要通過大量的設(shè)計(jì)工作、編碼工作來換取極高的靈活性。

既然是極高的靈活性,我們就來看一下這一方案是否足夠完美。引言中提到,使用結(jié)構(gòu)型的數(shù)據(jù)實(shí)體就喪失了對(duì)象實(shí)體的繼承和派生的性能。而有的時(shí)候我們的業(yè)務(wù)對(duì)象的確是有繼承和派生關(guān)系的。而單純的使用結(jié)構(gòu)型的業(yè)務(wù)實(shí)體(strong-typed DataSet)雖然不需要將數(shù)據(jù)的定義(schema)硬編碼到系統(tǒng)中,但是仍然有著一些不方便之處。集合數(shù)據(jù)的綁定就不必說了。比如我們現(xiàn)在需要的僅僅是一個(gè)單一的對(duì)象的時(shí)候,比如一個(gè)書店電子商務(wù)系統(tǒng)中需要一本數(shù)的詳細(xì)情況是,我們不得不使用BookData.Tables["BookMaster"].Rows[0][""]的形式來訪問一些特性。不如對(duì)象型實(shí)體Book.Name來的直接。而雖然說數(shù)據(jù)的格式是定義好的,但其中的細(xì)節(jié)肯定會(huì)有一些改變,這個(gè)時(shí)候?qū)嶓w的更改同樣會(huì)牽制很多地方的更改。

有沒有可能在集合數(shù)據(jù)綁定和與后端數(shù)據(jù)庫交互的時(shí)候使用“結(jié)構(gòu)型”,而在業(yè)務(wù)邏輯中使用對(duì)象型數(shù)據(jù)呢?本文就探討了一些實(shí)現(xiàn)方法。

綁上一個(gè)對(duì)象:數(shù)據(jù)與操作的分離

關(guān)于這一問題,本方案的最初想法是這樣的。既然我我們必須通過BookData.Tables["BookMaster"].Rows[0][]的方式訪問數(shù)據(jù)的細(xì)節(jié),為什么不給目前的DataSet增加一系列public property呢。但是一開始我就否定了這一想法。這是因?yàn)槲蚁氲浆F(xiàn)在我們作出的DataSet很純潔。僅僅用于承載數(shù)據(jù)。我們不可以僅僅因?yàn)槲覀兇嫒?shù)據(jù)方便就給DataSet很規(guī)則的內(nèi)部世界增添過多的行為。所以我想到了將原本應(yīng)該寫在DataSet里的代碼分離出來,集中在一個(gè)特別設(shè)計(jì)的“類”中。這樣就基本上形成了本文的中心思想-將操作與數(shù)據(jù)分離。

除了設(shè)計(jì)類型化的DataSet之外,為每個(gè)類型化的DataSet設(shè)計(jì)這么一組類:

他們之間互相有派生與繼承關(guān)系。甚至有公共的行為定義在基類或者接口中。另外,他們分別熟悉自己所對(duì)應(yīng)的類型化DataSet。通過公開一系列public property,將DataSet的數(shù)據(jù)公開來。包括其中包含的記錄數(shù)目,以及分別讀取每個(gè)單體對(duì)象(行)的細(xì)節(jié)數(shù)據(jù)(列)。通過這樣讓每個(gè)對(duì)象型實(shí)例“攜帶”一個(gè)DataSet,可以分別利用對(duì)象型和結(jié)構(gòu)型的優(yōu)點(diǎn)。例如針對(duì)以上的實(shí)例,我們把“商品”的結(jié)構(gòu)型數(shù)據(jù)實(shí)體(類型化的DataSet)定義為BookData,那么用來管理BookData數(shù)據(jù)的“對(duì)象型”類就叫做Book。Book可以訪問BookData包含的記錄數(shù)目,每條記錄的各個(gè)列,并且以BookColletion.Count, Book.Name的形式表現(xiàn)出來。

而當(dāng)不只一個(gè)表表示“商品”時(shí),可以定義Book對(duì)象自然地讀取相關(guān)表中的數(shù)據(jù)。(例如出版社名稱)

而除了讀取之外,可以對(duì)數(shù)據(jù)進(jìn)行增刪修改等操作。Books對(duì)象執(zhí)行該操作的時(shí)候即修改其攜帶的結(jié)構(gòu)型實(shí)體。這樣兩種實(shí)體相互依附,各司其職而密切合作。

此外,當(dāng)進(jìn)行實(shí)現(xiàn)時(shí),還有一些需要說明的地方:

1.對(duì)象的初始化過程:可以重載初始化過程,以對(duì)應(yīng)的結(jié)構(gòu)化DataSet為參數(shù)

2.一些特定操作:可以集中提取“結(jié)構(gòu)”里的特定數(shù)據(jù),為業(yè)務(wù)需求服務(wù)。其實(shí),多有需要熟悉DataSet機(jī)構(gòu)的操作都應(yīng)該集中到“對(duì)象”里來

3.public propery:get過程與set過程中必須檢查“結(jié)構(gòu)”是否為空對(duì)象,是否不包含任何行。而這一過程可以提取出來。

非常重要的是:這里的“對(duì)象型”實(shí)體,歸根結(jié)底還是實(shí)體,所進(jìn)行的操作,頁僅僅是一些簡(jiǎn)單的讀取、刪除、修改的操作,以及一些內(nèi)置的校驗(yàn)。至于和業(yè)務(wù)相關(guān)的邏輯,應(yīng)該由業(yè)務(wù)邏輯組件來承擔(dān)。目的僅僅是為了對(duì)應(yīng)用人員更友好。本文從立意到主題,并沒有與OR映射有任何關(guān)系。

零、一以及多的辨證統(tǒng)一

標(biāo)題上還有一個(gè)似乎是哲學(xué)問題的很嚇人的詞。其實(shí)這只是為了嚇唬各位。這的事情沒沒有那么玄奧。只是虛作聲勢(shì),嘩眾取寵而已。


我們注意到,以往我們從后端提取數(shù)據(jù)“填充”到類型化的DataSet中的時(shí)候,我們必須讀取數(shù)據(jù)前必須檢查BookData.Tables["BookMaster"].Rows.Count的不為0的時(shí)候才敢讀數(shù)。應(yīng)用了“對(duì)象化”之后,首先我們可以通過Count檢查,也可以定義在“結(jié)構(gòu)”中沒有行時(shí),返回空的屬性值以提示給用戶程序員。而另一問題時(shí),BookData中承載的數(shù)據(jù)時(shí)集合化的,而Book表示的是對(duì)象的單體。這就需要提前告訴Book讀取第幾行的數(shù)據(jù)。如果這一值沒有顯式的定義,那么就缺省得讀取第一行的數(shù)據(jù)。這樣不管提取到的數(shù)據(jù)沒有行、有單一行、還是多行,都單純地使用同一種表現(xiàn)方式。這就是零、一以及多的辨證統(tǒng)一。

讀者可能意識(shí)到了,Book為單數(shù),但是有時(shí)候表示復(fù)數(shù)的意義,例如有Count屬性。這也是這樣設(shè)計(jì)的一個(gè)極不優(yōu)雅的地方。

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多