.NET 業(yè)務(wù)框架開發(fā)實(shí)戰(zhàn)之四 后篇——業(yè)務(wù)層Mapping的選擇策略
前言:
在上一篇文章中提到了mapping,感覺很像在重新實(shí)現(xiàn)NHibernate。其實(shí)文章的本意是想反映出Richard在思考的時(shí)候的一些選擇:利用現(xiàn)有的,還是最后自己用別的方式實(shí)現(xiàn)。如果一上來就說什么什么好,那太武斷了,也很片面,系列文章反復(fù)的在強(qiáng)調(diào)一點(diǎn):技術(shù)有它的適用場景,沒有完美的技術(shù)。很多的朋友說本系列在近似的開發(fā)一個(gè)ORM,其實(shí)不是:ORM就是把數(shù)據(jù)庫表轉(zhuǎn)為數(shù)據(jù)實(shí)體,但是本篇中是使用已經(jīng)轉(zhuǎn)換后的數(shù)據(jù)實(shí)體。是把數(shù)據(jù)實(shí)體的數(shù)據(jù)給業(yè)務(wù)類。
而且本篇討論業(yè)務(wù)類中的mapping,也就是數(shù)據(jù)的獲取方式,當(dāng)然,業(yè)務(wù)類的設(shè)計(jì)遠(yuǎn)遠(yuǎn)不止這些。
開始之前希望在這下面的兩點(diǎn)上達(dá)到共識(shí):
1). 最好不要把DAL的數(shù)據(jù)實(shí)體(Linq或者Entity Framework生成的),或者原生的DataTable暴露給UI那邊(除非一定要,或者有特殊的原因)。
2). UI使用的是BLL類(或者基于消息的Scheme格式)。
今天的議題如下:
1).第二種Mapping方法。
2).第三種Mapping方法。
1. 第二種Mapping方法。
Richard思考了配置文件的方式,誠然用配置文件確實(shí)靈活,但是靈活也是有代價(jià)的,因?yàn)镕ramework最后還得公司的開發(fā)人員使用,過多的配置和過高的學(xué)習(xí)成本使得Framework失去了很大的意義。
Richard開始思考了,想到了還有一種最簡單的mapping的方式:就是直接一個(gè)個(gè)的賦值,如:
代碼
public class ProductBL { public string ProductName { get; set; } public decimal Price { get; set; } public string Description { get; set; } public void Mapping(m_Product productEntity) { this.ProductName = productEntity.Name; this.Price = productEntity.Price; this.Description = productEntity.Description; } }
很明顯,這個(gè)過程很簡單卻很繁瑣。
和之前使用配置文件的方式相比:
優(yōu)點(diǎn):
1). 便于使用和理解
2). 便于調(diào)試
缺點(diǎn):
1). 和數(shù)據(jù)實(shí)體耦合的很緊(其實(shí)這不算是缺點(diǎn),這是和之前配置文件的方式比較而言認(rèn)為缺點(diǎn))。上面的代碼中就直接使用了m_Product.(大家可以參看之前一篇文章中用配置文件的優(yōu)缺點(diǎn))
2). 編寫的過程很繁瑣。全部是手動(dòng)的mapping。而且還有關(guān)鍵的一點(diǎn)就是:查詢對(duì)象怎么生成最終的SQL語句?
例如,下面的代碼:
ICriteria condition=CriteriaFactory.Create(typeof(ProductBL).Where("ProductName", Operation.Equal,"book");
如果采用配置文件的mapping方式,很清楚:在配置文件中ProductBL的ProductName對(duì)應(yīng)m_Product實(shí)體的Name字段,也就是對(duì)應(yīng)數(shù)據(jù)庫表m_Product的Name字段(因?yàn)樵贐LL中使用的是通過linq或者Entity Framework生成的m_Product實(shí)體)。上面的查詢對(duì)象最后生成類似select * from m_Product where Name=’book’的語句。
Richard想到NHibernate的實(shí)現(xiàn):在NHibernate也有查詢對(duì)象,在NHibernate中的查詢對(duì)象的實(shí)現(xiàn)也是依賴NHibernate的那個(gè)mapping的配置文件的。
并不是說沒有查詢對(duì)象就不行,不用查詢對(duì)象,用Linq和Entity Framework也是可以實(shí)現(xiàn)的。但是數(shù)據(jù)層就沒有“以不變應(yīng)萬變”了的效果,而且開發(fā)人員要掌握各種的數(shù)據(jù)訪問技術(shù):ADO.NET, Linq等。(可以參看.NET 分布式架構(gòu)開發(fā)實(shí)戰(zhàn)之三 數(shù)據(jù)訪問深入一點(diǎn)的思考一文)。
現(xiàn)在Richard面臨的問題就是:
1). 不用配置文件mapping,這樣查詢對(duì)象就不好實(shí)現(xiàn)。
2). 手動(dòng)的敲入代碼mapping,重復(fù)的勞動(dòng)。
Richard思考是否更好的方式解決上面的問題。于是第三種方式就產(chǎn)生了。
3. 第三種Mapping方法。
第三種mapping的方法就是綜合了之前兩種mapping的優(yōu)點(diǎn),而避開了他們的缺點(diǎn)。
Richard想到解決手動(dòng)mapping的方法就是:圖形化的代碼生成來代替手寫代碼。而且要想辦法保存數(shù)據(jù)庫字段的一些信息。
很巧的就是:linq和EF生成的實(shí)體中的字段信息就反映了數(shù)據(jù)表字段的信息。這點(diǎn)可以利用起來。下面的草圖是用Visio畫出的,代表了Richard的想法。其實(shí)Richard也沒有一下就開發(fā)出下面的工具,一切還是處于設(shè)計(jì)階段。
Richard設(shè)計(jì)出了自動(dòng)生成代碼的工具(工具的開發(fā)Richard思考過了,可以采用最簡單的實(shí)現(xiàn)方式:一個(gè)Windows程序。也想過用DSL工具開發(fā),但是DSL得學(xué)習(xí)過程還是有點(diǎn)復(fù)雜的)。
注:雖然說是代碼生成工具,其實(shí)一開始Richard也是想的很簡單:就是一個(gè)寫文本的操作。
在上面的界面中,選擇要和哪個(gè)數(shù)據(jù)實(shí)體類mapping,可以通過選擇“MappingName”來實(shí)現(xiàn)。然后點(diǎn)擊“Properties”按鈕,出現(xiàn)了如下的界面:
這是一個(gè)專門用來配置mapping的界面:點(diǎn)擊“Add”按鈕,添加一個(gè)業(yè)務(wù)類的屬性,然后用”MappingTo”來設(shè)置這個(gè)屬性的數(shù)據(jù)從數(shù)據(jù)實(shí)體類的那個(gè)字段中獲取。在選擇數(shù)據(jù)實(shí)體字段的時(shí)候,也把這個(gè)選中數(shù)據(jù)實(shí)體的字段信息保存起來,供給之后的查詢對(duì)象使用。
基本思路Richard已經(jīng)有了,F(xiàn)在的問題就是把上面選選中數(shù)據(jù)字段信息保存在哪里,而且還得和業(yè)務(wù)類的屬性對(duì)應(yīng),例如,Id對(duì)應(yīng)業(yè)務(wù)類Product的ProductId,而不是其他的屬性。
在mapping的時(shí)候,一般是在業(yè)務(wù)類中定義一個(gè)屬性,然后賦值:
public string ProductId { get; set; } this.ProductName = productEntity.Id;
為了保存數(shù)據(jù)實(shí)體字段的信息,業(yè)務(wù)類的屬性聲明就改為下面了:
代碼
public static readonly PropertyInfo<int> ProductIdProperty = RegisterProperty( typeof(Product), new PropertyInfo<int>("ProductId",typeof(M_Product)","Id")); public string ProductId { get { return ReadProperty(ProductIdProperty); } set { LoadProperty(ProductIdProperty, value); } }
上面的代碼通過生成的方式就比較方便,而且上面的屬性聲明還有更多其他的用途。初一看和WPF中依賴屬性很像,確實(shí)思路也是從WPF借鑒而來的。這里簡稱“Mapping屬性”。
今天就寫到這里,真是對(duì)不住大家,因?yàn)楸酒獙懙谋容^的啰嗦,而且還沒有寫完。下篇講述Mapping屬性的實(shí)現(xiàn)原理和原因,就是為什么要是用ProductIdProperty那種聲明方式。
版權(quán)為小洋和博客園所有,歡迎轉(zhuǎn)載,轉(zhuǎn)載請(qǐng)標(biāo)明出處給作者。 http://www.cnblogs.com/yanyangtian
轉(zhuǎn)載:http://www.cnblogs.com/yanyangtian/archive/2010/06/09/1754426.html
本文鏈接:http://m.95time.cn/tech/program/2010/7759.asp
出處:博客園
責(zé)任編輯:bluehearts
上一頁 .NET業(yè)務(wù)框架開發(fā)實(shí)戰(zhàn)之四 后篇 [1] 下一頁
◎進(jìn)入論壇網(wǎng)絡(luò)編程版塊參加討論
|