日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷解決方案
系統(tǒng)架構(gòu)師談企業(yè)應(yīng)用架構(gòu)之?dāng)?shù)據(jù)訪問層

一、上章回顧

創(chuàng)新互聯(lián)專注于北屯網(wǎng)站建設(shè)服務(wù)及定制,我們擁有豐富的企業(yè)做網(wǎng)站經(jīng)驗(yàn)。 熱誠(chéng)為您提供北屯營(yíng)銷型網(wǎng)站建設(shè),北屯網(wǎng)站制作、北屯網(wǎng)頁(yè)設(shè)計(jì)、北屯網(wǎng)站官網(wǎng)定制、微信小程序定制開發(fā)服務(wù),打造北屯網(wǎng)絡(luò)公司原創(chuàng)品牌,更為您提供北屯網(wǎng)站排名全網(wǎng)營(yíng)銷落地服務(wù)。

  上篇我們簡(jiǎn)單講述了服務(wù)層架構(gòu)模式中的幾種,并且講解了服務(wù)層的作用及相關(guān)的設(shè)計(jì)規(guī)范,其實(shí)我們應(yīng)該知道,在業(yè)務(wù)邏輯層中使用領(lǐng)域模型中使用服務(wù)層才

  能發(fā)揮出***的優(yōu)勢(shì),如果說我們?cè)跇I(yè)務(wù)邏輯層還是使用非領(lǐng)域模型的模式話,服務(wù)層的作用僅體現(xiàn)在解耦作用。其實(shí)在業(yè)務(wù)邏輯層采用領(lǐng)域模型時(shí),我們前面說的持

  久化透明的技術(shù),其實(shí)我們可以通過服務(wù)層來做,我們?cè)诜?wù)層中處理領(lǐng)域?qū)ο笮畔⒌某志没僮?。?dāng)然本篇可能不會(huì)深入討論持久化透明的具體實(shí)現(xiàn),后面會(huì)單獨(dú)開

  篇來講述,我們先來回顧下上篇講解的內(nèi)容:

上圖大概描述了上篇我們講解的內(nèi)容,如果您想要詳細(xì)的了解服務(wù)

  層的相關(guān)內(nèi)容,請(qǐng)參考:系統(tǒng)架構(gòu)師-基礎(chǔ)到企業(yè)應(yīng)用架構(gòu)-服務(wù)層,后續(xù)我們將會(huì)對(duì)一些前端的服務(wù)層還會(huì)進(jìn)行擴(kuò)展的講解,請(qǐng)大家提出報(bào)告意見和建議。

  二、摘要

  本篇將主要以系統(tǒng)中與數(shù)據(jù)庫(kù)存儲(chǔ)介質(zhì)進(jìn)行交互的數(shù)據(jù)訪問層進(jìn)行詳細(xì)的介紹講解,我想這塊也是大家比較熟悉也是經(jīng)常在項(xiàng)目中一定會(huì)用到的部分,我們知道

  數(shù)據(jù)訪問層通常我們都把這塊的內(nèi)容提升出來,寫成通用的類庫(kù),在我們前面講解的分層架構(gòu)的系統(tǒng)中,基本上可以說業(yè)務(wù)對(duì)象中的數(shù)據(jù)都要通過數(shù)據(jù)訪問層將業(yè)

  務(wù)數(shù)據(jù)持久化到存儲(chǔ)介質(zhì)中。其實(shí)目前有很多的好的ORM框架已經(jīng)很好的實(shí)現(xiàn)了數(shù)據(jù)訪問層,而且得到了很廣泛的應(yīng)用,當(dāng)然我們本篇也會(huì)以這些通用的框架為例舉

  例說明數(shù)據(jù)訪問層中的一些設(shè)計(jì)模式。本章將會(huì)以下列幾個(gè)典型關(guān)注點(diǎn)展開去講:

  1、數(shù)據(jù)訪問層的職責(zé)及與其他組件的交互。

  2、如何設(shè)計(jì)自己的數(shù)據(jù)訪問層。

  3、實(shí)現(xiàn)數(shù)據(jù)訪問層必須滿足的4個(gè)基本要求,持久化CRUD、查詢服務(wù)、事務(wù)服務(wù)、實(shí)現(xiàn)并發(fā)等。

  4、結(jié)合目前流行的幾類框架分析框架提供的數(shù)據(jù)訪問層功能的優(yōu)劣。

  下面我們將針對(duì)上面的幾個(gè)關(guān)注點(diǎn)依次展開去說,希望能通過本文的講解,讓您對(duì)數(shù)據(jù)庫(kù)訪問層有個(gè)更深刻的認(rèn)識(shí)和了解。

  三、本章大綱

  1、上章回顧。

  2、摘要。

  3、本章大綱。

  4、數(shù)據(jù)訪問層介紹。

  5、如何設(shè)計(jì)數(shù)據(jù)訪問層。

  6、實(shí)現(xiàn)數(shù)據(jù)訪問的四項(xiàng)原則。

  7、本章總結(jié)。

  8、系列進(jìn)度。

  9、下篇預(yù)告。

  四、數(shù)據(jù)庫(kù)訪問層簡(jiǎn)介

  本節(jié)將會(huì)主要針對(duì)數(shù)據(jù)訪問層的功能及職責(zé)進(jìn)行講解,分析之前在業(yè)務(wù)邏輯層中的四種模式與數(shù)據(jù)訪問層之間的關(guān)系。我們閑來看看數(shù)據(jù)訪問層與業(yè)務(wù)邏輯層中的

  四種模式之間的關(guān)系。

  我們?cè)诒竟?jié)中的講解主要是以領(lǐng)域模型為例進(jìn)行分析講解,因?yàn)橹挥蓄I(lǐng)域模型模式,我們才能將數(shù)據(jù)訪問層抽離出來,分成單獨(dú)的層,這樣能夠做到領(lǐng)域?qū)ο蟪志?/p>

  化透明。接下來我們來看看數(shù)據(jù)訪問層都需要提供什么要的功能及數(shù)據(jù)訪問層本身的職責(zé)是什么。

  數(shù)據(jù)庫(kù)訪問層是唯一知道如何操作存儲(chǔ)介質(zhì)的入口,可以這么來說,基于數(shù)據(jù)訪問層之上,我們調(diào)用數(shù)據(jù)庫(kù)訪問層提供的方法,我們就能完成數(shù)據(jù)的存儲(chǔ)與讀取,

  所以我們可以知道,數(shù)據(jù)訪問層應(yīng)該是與數(shù)據(jù)庫(kù)直接是獨(dú)立的。還有就是我們的數(shù)據(jù)訪問層如何能實(shí)現(xiàn)不同類型的數(shù)據(jù)庫(kù)的動(dòng)態(tài)的切換,而我們不需要修改任何的程序

  功能等,可能我們?cè)陂_發(fā)的過程中都會(huì)遇到這樣的問題。所以我們希望可以對(duì)數(shù)據(jù)訪問層完成動(dòng)態(tài)的配置,通過不同的配置項(xiàng)完成對(duì)象數(shù)據(jù)庫(kù)訪問的切換,這里我想大

  家都是比較熟悉的,通過XML配置文件來完成數(shù)據(jù)庫(kù)的切換,前面我們說了我們的需求,是必須實(shí)現(xiàn)無縫的數(shù)據(jù)庫(kù)的切換,那么我們?nèi)绾螌?shí)現(xiàn)呢,這里我們可以通過定

  義一個(gè)數(shù)據(jù)庫(kù)訪問接口,然后通過實(shí)現(xiàn)不同的數(shù)據(jù)庫(kù)的細(xì)節(jié),來實(shí)現(xiàn)這樣的切換。目前很多流行的框架都是采用這樣的方式來實(shí)現(xiàn)數(shù)據(jù)庫(kù)的動(dòng)態(tài)切換。當(dāng)然有時(shí)候我們

  的項(xiàng)目中肯能不讓我們使用開源的通用框架,這時(shí)候我們可能就需要自己去實(shí)現(xiàn)這些數(shù)據(jù)訪問層的具體細(xì)節(jié)。

  當(dāng)然數(shù)據(jù)訪問層都必須能夠?qū)?yīng)用程序中的數(shù)據(jù)持久化到存儲(chǔ)介質(zhì)中,通常我們使用的數(shù)據(jù)都是關(guān)系型的數(shù)據(jù)庫(kù),但是我們知道我們?cè)诔绦虻拈_發(fā)中,通常采用的

  模型都是對(duì)象模型,那么如何實(shí)現(xiàn)對(duì)象模型與關(guān)系模型直接的互相的轉(zhuǎn)換就顯得非常的重要。當(dāng)然這是數(shù)據(jù)訪問層的重要功能。通常來說,業(yè)務(wù)邏輯層及服務(wù)層不了解

  數(shù)據(jù)庫(kù)訪問的具體細(xì)節(jié),他們都需要通過數(shù)據(jù)訪問層來實(shí)現(xiàn)數(shù)據(jù)的交互。一般來說在領(lǐng)域模型中,數(shù)據(jù)訪問通常都是在服務(wù)層中進(jìn)行調(diào)用的,而業(yè)務(wù)邏輯層并不關(guān)注數(shù)

  據(jù)持久化,所以我們前面說的持久化透明的方式也是由此方式來實(shí)現(xiàn)。

  上面我們啰嗦了一大堆,基本上說了數(shù)據(jù)訪問層的基本需求功能:

下面我們來看看數(shù)據(jù)訪問層的幾個(gè)基本職責(zé)

  首先、數(shù)據(jù)訪問層應(yīng)該提供基本的持久化操作CRUD的操作,我們知道數(shù)據(jù)訪問層是唯一能操作數(shù)據(jù)庫(kù)的一層,因?yàn)槲覀冊(cè)谠O(shè)計(jì)時(shí)需要注意,系統(tǒng)的其他層不能

  包含操作數(shù)據(jù)庫(kù)的相關(guān)功能

這里我們通過類圖可以看到,通過提供與類對(duì)應(yīng)的數(shù)據(jù)庫(kù)操作類來提供

  相應(yīng)的持久化操作方法,當(dāng)然這不是唯一方式,可行的方式有很多。我們后面會(huì)詳細(xì)討論。

  其次、應(yīng)該提供能夠滿足類中信息的讀取操作,一般情況下來說我們經(jīng)常使用的是,根據(jù)主鍵查詢某個(gè)對(duì)象的信息,或者是查詢所有的記錄,或者是根據(jù)條件返

  回滿足的集合。

  當(dāng)然我們這里定義的查詢類可能是通用的形式,通過泛型的形式來做。但是我們知道

  領(lǐng)域模型中肯定會(huì)有引用對(duì)象的情況,那么對(duì)于這樣的情況我們?nèi)绾蝸碜瞿??我們一般是通過延遲加載的形式來處理這樣的要求,我們后面會(huì)依次講解。我們來看看上

  面的通用形式的簡(jiǎn)單代碼格式:

 
 
 
 
  1.   public class QueryHelper
  2.   {
  3.   /// 
  4.   /// 根據(jù)主鍵返回對(duì)象
  5.   /// 
  6.   /// 
  7.   /// 
  8.   /// 
  9.   public T GetObjectByKey(object key)
  10.   {
  11.   return default(T);
  12.   }
  13.   /// 
  14.   /// 獲取指定類型對(duì)象的總記錄數(shù)
  15.   /// 
  16.   /// 
  17.   /// 
  18.   /// 
  19.   public int GetCount(object key)
  20.   {
  21.   return 0;
  22.   }
  23.   /// 
  24.   /// 返回指定類型的所有對(duì)象集合
  25.   /// 
  26.   /// 
  27.   /// 
  28.   public List GetAll()
  29.   {
  30.   return new List();
  31.   }
  32. }

  再次、數(shù)據(jù)庫(kù)訪問必須提供事務(wù)的管理,可以說不提供事務(wù)操作的數(shù)據(jù)訪問層就沒有辦法使用,因?yàn)檫@樣的數(shù)據(jù)訪問層構(gòu)建的系統(tǒng)是不安全的。特別是批量持久

  化的過程中,事務(wù)不但能夠減少與數(shù)據(jù)庫(kù)操作的次數(shù),而且根據(jù)事務(wù)的四個(gè)特性可以提供更好的安全性。我們來回顧下事務(wù)的四個(gè)特性:

  我想我這里就不用一一解釋了,大家都明白的。我們?cè)跀?shù)據(jù)訪問層的設(shè)計(jì)中是通過引入

  “工作單元”來實(shí)現(xiàn)事務(wù)管理的,工作單元后面會(huì)講述到工作單元內(nèi)提供的方法及事務(wù)性。

  ***、數(shù)據(jù)訪問層必須提供處理并發(fā)的功能,我們?cè)谙到y(tǒng)訪問的人較多的情況時(shí)肯定會(huì)出現(xiàn)并發(fā)的情況,數(shù)據(jù)訪問層如何處理這樣的情況就顯得極其重要了,在

  一個(gè)多用戶并發(fā)的系統(tǒng)中,通過前面提到的事務(wù)來處理,這時(shí)候可能就會(huì)出現(xiàn)數(shù)據(jù)庫(kù)完整性的問題,例如這樣的情況,一個(gè)用戶現(xiàn)在在編輯自己的個(gè)人信息,例如將生

  日修改為1985年3月20日,這個(gè)用戶對(duì)應(yīng)的ID是298,這時(shí)候他只是修改了,但是還沒有提交,此時(shí)管理員也修改了,比如說修改了ID為298的這個(gè)用戶信息的地址或

  者其他信息,并且提交,此時(shí),用戶將自己編輯的生日提交了,那么數(shù)據(jù)庫(kù)中對(duì)應(yīng)的ID為298的數(shù)據(jù)信息就會(huì)是***修改的數(shù)據(jù)信息,那么之前管理員修改的數(shù)據(jù)信息

  就會(huì)發(fā)生丟失,雖然是修改的可能字段不是同一個(gè)字段,這就和我們底層實(shí)現(xiàn)的數(shù)據(jù)訪問層有關(guān),當(dāng)然如果說我們?cè)跀?shù)據(jù)訪問層實(shí)現(xiàn)了,只更新修改過的數(shù)據(jù)列的值的

  話,那么可能不會(huì)存在這樣的情況,當(dāng)然這就和我們底層實(shí)現(xiàn)的數(shù)據(jù)訪問層的機(jī)制有關(guān)。

  下面我們通過圖形的方式來說明,更容易理解:

我們來看看可能的幾種方案,可以對(duì)這樣的并發(fā)做出相應(yīng)的處理?

當(dāng)然這里只是提供了幾個(gè)簡(jiǎn)單可行的辦法,當(dāng)然如果大家還

  有更好的辦法,可以告訴我,不勝感激。

  當(dāng)然上面的四個(gè)基本職責(zé)是我們?cè)跀?shù)據(jù)訪問層必須提供的,還應(yīng)該提供緩存機(jī)制,延遲加載等等包括一些性能方面的優(yōu)化的設(shè)計(jì)等,這些都在后面講解吧。

  下面我們來看看數(shù)據(jù)訪問層與其他層直接的關(guān)系與交互,我們前面說過,在領(lǐng)域模型下,業(yè)務(wù)邏輯層中的數(shù)據(jù)的持久化都是通過服務(wù)層來完成的,下面我們來看

  看各層之間的關(guān)系。我們先來看看服務(wù)層與數(shù)據(jù)訪問層之間的關(guān)系。

  服務(wù)層與數(shù)據(jù)訪問層之間進(jìn)行交互,服務(wù)層通過DTO與UI層進(jìn)行交互,服務(wù)層通過組織業(yè)務(wù)邏輯層中的對(duì)象來實(shí)

  現(xiàn)業(yè)務(wù)流,然后通過調(diào)用數(shù)據(jù)訪問層將業(yè)務(wù)流中的相應(yīng)數(shù)據(jù)進(jìn)行持久化,通過數(shù)據(jù)訪問層來初始化領(lǐng)域模型。置于直接在表現(xiàn)層中使用數(shù)據(jù)訪問層的功能,我們通常是

  不推薦這樣做的,一般我們不會(huì)這么做的,我這里就不詳細(xì)的闡述。

  五、如何設(shè)計(jì)數(shù)據(jù)訪問層

  本節(jié)將詳細(xì)的講述如何設(shè)計(jì)出自己的數(shù)據(jù)訪問層,滿足上述的幾個(gè)基本要求,那么可以說就算完成了基本的數(shù)據(jù)訪問層的功能,其實(shí)如果我們從頭開始開發(fā)一個(gè)

  這樣的數(shù)據(jù)訪問層將是非常大的工作量,目前流行的很多的ORM框架已經(jīng)提供了豐富的數(shù)據(jù)訪問層的功能,能夠非常好的滿足上述的幾項(xiàng)職責(zé)。當(dāng)然本節(jié)還是會(huì)結(jié)合代

  碼來說說數(shù)據(jù)訪問層的具體實(shí)現(xiàn)。

  我們前面講述了數(shù)據(jù)訪問的3個(gè)基本的功能需求,數(shù)據(jù)庫(kù)獨(dú)立性,可配置性及持久化對(duì)象模式(對(duì)象模型與關(guān)系模型的轉(zhuǎn)換),我們這里先看如何實(shí)現(xiàn)數(shù)據(jù)庫(kù)的獨(dú)立

  性,我們提出滿足數(shù)據(jù)庫(kù)的無縫遷移,通過XML配置文件,配置不同的數(shù)據(jù)庫(kù)鏈接來實(shí)現(xiàn)這樣的功能,那么首先我們需要定義針對(duì)不同數(shù)據(jù)庫(kù)具體實(shí)現(xiàn),才能完成后續(xù)

  的操作,既然我們這里要降低耦合,那么根據(jù)我們前面的面向?qū)ο蟮脑O(shè)計(jì)原則與規(guī)范知道,我們推薦使用面向接口的編程的方式,來盡量的降低耦合性。我們來看看具

  體的代碼。首先我們定義一個(gè)通用的數(shù)據(jù)訪問層的接口。

 
 
 
 
  1.   /// 
  2.   /// 數(shù)據(jù)訪問層統(tǒng)一接口
  3.   /// 
  4.   public interface IDALInterface
  5.   {
  6.   //CUD 持久化操作
  7.   /// 
  8.   /// 創(chuàng)建新的對(duì)象
  9.   /// 
  10.   /// 
  11.   /// 
  12.   int Create(object model);
  13.   /// 
  14.   /// 更新對(duì)象
  15.   /// 
  16.   /// 
  17.   /// 
  18.   int Update(object model);
  19.   /// 
  20.   /// 刪除對(duì)象
  21.   /// 
  22.   /// 
  23.  /// 
  24.   int Delete(object model);
  25.   //R 查詢服務(wù)
  26.   /// 
  27.   /// 查詢所有記錄
  28.   /// 
  29.   /// 泛型模型
  30.   /// 
  31.   IList GetAll() where T : class,new();
  32.   /// 
  33.   /// 查詢滿足條件的集合
  34.   /// 
  35.   /// 
  36.   /// 
  37.   /// 
  38.   IList GetListByQuery(WhereCondition whereCondition) where T : class,new();
  39.   /// 
  40.   /// 返回總行數(shù)
  41.   /// 
  42.   /// 
  43.   /// 
  44.   int GetCount();
  45.   /// 
  46.   /// 返回滿足條件的總行數(shù)
  47.   /// 
  48.  /// 
  49.   /// 
  50.   /// 
  51.   int GetCount(WhereCondition whereCondition);
  52.   /// 
  53.   /// 根據(jù)主鍵返回對(duì)象模型
  54.   /// 
  55.   /// 
  56.   /// 
  57.   /// 
  58.   T GetModelByKey(object key) where T : class,new();
  59.   //事務(wù)
  60.   /// 
  61.   /// 是否事務(wù)執(zhí)行
  62.   /// 
  63.   bool IsTransaction
  64.   {
  65.   get;
  66.   }
  67.   /// 
  68.   /// 開始事務(wù)
  69.   /// 
  70.   void BeginTransaction();
  71.   /// 
  72.   /// 提交事務(wù)
  73.   /// 
  74.   void Commit();
  75.   /// 
  76.   /// 回滾事務(wù)
  77.   /// 
  78.   void Rollback();
  79.   }

  這里定義了基本的幾個(gè)簡(jiǎn)單方法,當(dāng)然其中并沒有包括并發(fā)的處理,后面會(huì)講到這塊的處理方案的實(shí)現(xiàn), 前面介紹了幾種可行的實(shí)現(xiàn)方式。接口定義好了之后,

  數(shù)據(jù)層的具體代碼我這里就不一一的定義貼出來了,因?yàn)槊糠N不同的數(shù)據(jù)庫(kù)類型就要分別實(shí)現(xiàn),我們這里講解2中不同類型的實(shí)現(xiàn)思路吧,

  我們這里講解2中實(shí)現(xiàn)動(dòng)態(tài)創(chuàng)建具體數(shù)據(jù)訪問組件的方式,我們先來講講插件模式。

  插件模式

  插件模式:插件模式就是通過外部配置文件中讀取要?jiǎng)?chuàng)建的組件的類型信息,然后調(diào)用組件服務(wù),插件模式的關(guān)鍵點(diǎn)就是服務(wù)不會(huì)與具體實(shí)現(xiàn)聯(lián)系起來,在我們的

  分層結(jié)構(gòu)中的解釋就是,服務(wù)層中調(diào)用數(shù)據(jù)訪問層中的組件服務(wù),服務(wù)層不關(guān)系具體的調(diào)用方式,服務(wù)層只關(guān)心服務(wù)。而具體的數(shù)據(jù)訪問組件是通過配置文件來動(dòng)態(tài)的

  創(chuàng)建,當(dāng)然這就需要使用.NET中的反射的功能。我們來看個(gè)圖形畫的描述:

反射工廠通過讀取配置文件中具體的數(shù)據(jù)配置項(xiàng)及數(shù)據(jù)訪問的具

  體服務(wù)組件類型,通過反射工廠來動(dòng)態(tài)的創(chuàng)建,好了我們來看看實(shí)例代碼及配置文件。

 
 
 
 
  1.   
  2.   
  3.   
  4. value="Data Source=.SQLEXPRESS;Initial Catalog=EasyStore;User ID=sa;Password=123456" />  
  5. value="Data Source=.SQLEXPRESS;Initial Catalog=EasyStore;User ID=sa;Password=123456" />
  6.   
  7. value="DAL.SQLServer" />  value="DAL.SQLServer" />
  8.   
  9. value="DAL.SQLServer" />  value="DAL.SQLServer" />
  10.  

  上面的配置文件中的ConnectionItem 節(jié)點(diǎn)中配置了數(shù)據(jù)庫(kù)訪問的鏈接字符串,DALType 定義了數(shù)據(jù)訪問層組件的類型。我們下來看看反射工廠的示例代碼實(shí)

  現(xiàn)。

 
 
 
 
  1.   public class DALHelper
  2.   {
  3.   private static IDALInterface instance;
  4.   public static IDALInterface GetDAL()
  5.   {
  6.   string assambly = XmlHelper.getVlaue("Assembly");//這里應(yīng)該是自定義的讀取XML節(jié)點(diǎn)的方式
  7.   string type = XmlHelper.getVlaue("DALType");
  8.   Assembly asm = Assembly.Load(assambly);
  9.   instance = (IDALInterface)asm.CreateInstance(type);
  10.   return instance;
  11.   }
  12.   }

  我們接下來看看如何使用這個(gè)數(shù)據(jù)訪問層去實(shí)現(xiàn)相應(yīng)的持久化操作:

 
 
 
 
  1.   public class TestService
  2.   {
  3.   private IDALInterface DAL;
  4.   public TestService()
  5.   {
  6.   DAL = DALHelper.GetDAL();
  7.   }
  8.   public void Create(Test test)
  9.   {
  10.   //相應(yīng)的判定操作
  11.   //創(chuàng)建對(duì)象
  12.  DAL.Create(test);
  13.   }
  14.   }

  這樣就實(shí)現(xiàn)了在服務(wù)層對(duì)數(shù)據(jù)訪問層的調(diào)用操作,這里是通過接口調(diào)用的方式來實(shí)現(xiàn)。我們?cè)賮砜纯纯刂品崔D(zhuǎn)的實(shí)現(xiàn)方式吧。

  控制反轉(zhuǎn)

  控制反轉(zhuǎn)我們?cè)谠O(shè)計(jì)規(guī)范與原則中有過講解,控制反正通過動(dòng)態(tài)的將組件注入到引用該組件的對(duì)象中的形式,然后讓引用該組件的對(duì)象使用組件的服務(wù),DI依賴注

  入可以看作是控制反轉(zhuǎn)的一個(gè)應(yīng)用實(shí)例,我們可以把控制反轉(zhuǎn)看作是一個(gè)原則。

  下面我們來看看我們?nèi)绾瓮ㄟ^控制反正的方式來實(shí)現(xiàn)數(shù)據(jù)訪問層的平滑遷移。當(dāng)然我們知道,肯定是通過動(dòng)態(tài)注入的方式來實(shí)現(xiàn),當(dāng)然目前主流的也有很多的IOC動(dòng)

  態(tài)注入框架,下面我們將會(huì)借助一些框架來說明如何實(shí)現(xiàn)這樣的功能。

  本文將以Enterprise Library5.0為例進(jìn)行講解動(dòng)態(tài)注入的形式。我們先來看看配置文件的設(shè)置

我們來看看通過一個(gè)中間類去實(shí)現(xiàn)相應(yīng)的注冊(cè)代碼:

 
 
 
 
  1.   /// 
  2.   /// 用于動(dòng)態(tài)完成代碼注入的公共類
  3.  /// 
  4.   public class IOCContainer
  5.   {
  6.   private static IUnityContainer container;
  7.   private UnityConfigurationSection section;
  8.   public void InitIOC()
  9.   {
  10.   container = new UnityContainer();
  11.   section = (UnityConfigurationSection)System.Configuration.ConfigurationManager.GetSection("unity");
  12.   section.Configure(container);
  13.   }
  14.   public static IDALInterface GetDAL()
  15.   {
  16.   return container.Resolve();
  17.   }
  18.   }

  通過上述代碼我們實(shí)現(xiàn)了,動(dòng)態(tài)的創(chuàng)建數(shù)據(jù)訪問層組件實(shí)例,下面我們來看看依賴注入的方式去完成相應(yīng)的持久化的功能。我們來看看服務(wù)層的代碼

 
 
 
 
  1.   /// 
  2.   /// 測(cè)試服務(wù)層
  3.   /// 
  4.   public class TestService
  5.   {
  6.   private IDALInterface DAL;
  7.   public TestService(IDALInterface dal)
  8.   {
  9.   DAL = dal;
  10.   }
  11.   public void Save(Test test)
  12.   {
  13.   DAL.Create(test);
  14.   }
  15.   }

  這里我們是采用構(gòu)造函數(shù)注入的方式來實(shí)現(xiàn)數(shù)據(jù)訪問層的動(dòng)態(tài)注入的,當(dāng)然除了構(gòu)造函數(shù)注入,還有其他的方式,我們這里只是舉例說明,一般來說依賴注入有

  如下的幾種形式

具體的我這里就不舉例說明了,大家可以網(wǎng)上查查有很多的例

  子,我們平時(shí)也常用這些方式。

  六、實(shí)現(xiàn)數(shù)據(jù)訪問的四項(xiàng)原則

  在第四節(jié)中我們講解了數(shù)據(jù)訪問層的四個(gè)原則,那么我們?cè)谧约旱臄?shù)據(jù)訪問層中如何實(shí)現(xiàn)這幾個(gè)原則呢,我想針對(duì)***個(gè)原則持久化的原則,我們前面只是簡(jiǎn)單

  的講解如何實(shí)現(xiàn)數(shù)據(jù)庫(kù)的獨(dú)立性,下面我們先來看看持久化的操作,也就是我們說的CUD的操作,并不包括具體的查詢服務(wù),查詢服務(wù)也是我們數(shù)據(jù)訪問層必須提供四

  個(gè)原則之一,我們后面都會(huì)講解,我們先來看看CUD的實(shí)現(xiàn)。我們?cè)谧龀志没?wù)的時(shí)候,一般情況下,我們會(huì)定義一個(gè)統(tǒng)一的數(shù)據(jù)訪問層接口,然后提供持久化服

  務(wù),事務(wù)等等,通常有一些數(shù)據(jù)訪問層共性的部分,我們都通過一個(gè)抽象類來實(shí)現(xiàn),抽象類將實(shí)現(xiàn)接口中的部分功能,然后通過定義一些抽象成員函數(shù),讓具體的數(shù)據(jù)

  訪問層去實(shí)現(xiàn)相應(yīng)的功能。我們這里以上節(jié)我們定義的IDALInterface為例講解基類的簡(jiǎn)單實(shí)現(xiàn)。

  我們將原來的接口層進(jìn)行相關(guān)的優(yōu)化操作將CUD操作單獨(dú)抽取出來,通過ICUDMapper接口來定義

 
 
 
 
  1.   /// 
  2.   /// 數(shù)據(jù)庫(kù)持久化訪問器
  3.   /// 
  4.   public interface ICUDMapper
  5.   {
  6.   //CUD 持久化操作
  7.   /// 
  8.   /// 創(chuàng)建新的對(duì)象
  9.  /// 
  10.   /// 
  11.   /// 
  12.   int Create(object model);
  13.   /// 
  14.   /// 更新對(duì)象
  15.   /// 
  16.   /// 
  17.   /// 
  18.   int Update(object model);
  19.   /// 
  20.   /// 刪除對(duì)象
  21.   /// 
  22.   /// 
  23.   /// 
  24.   int Delete(object model);
  25.  }

  然后我們來看看基類接口層的簡(jiǎn)單實(shí)現(xiàn),作為所有數(shù)據(jù)訪問層的父類

 
 
 
 
  1.   public abstract class BaseDAL : IDALInterface,IDisposable
  2.   {
  3.   protected abstract ICUDMapper GetMapper();
  4.   //CUD 持久化操作
  5.   /// 
  6.   /// 創(chuàng)建新的對(duì)象
  7.   /// 
  8.   /// 
  9.   /// 
  10.  public int Create(object model)
  11.   {
  12.   return GetMapper().Create(model);
  13.   }
  14.   /// 
  15.   /// 更新對(duì)象
  16.   /// 
  17.   /// 
  18.   /// 
  19.   public int Update(object model)
  20.   {
  21.   return GetMapper().Update(model);
  22.   }
  23.   /// 
  24.   /// 刪除對(duì)象
  25.   /// 
  26.  /// 
  27.   /// 
  28.   public int Delete(object model)
  29.   {
  30.   return GetMapper().Delete(model);
  31.   }
  32.   #region IDisposable 成員
  33.   /// 
  34.   /// 是否數(shù)據(jù)庫(kù)訪問組件資源
  35.  /// 
  36.   public void Dispose()
  37.   {
  38.   }
  39.   #endregion
  40.   }

  當(dāng)然這里只貼出實(shí)例代碼。當(dāng)然我采用這樣的方式,就是利用我們之前的一篇:Step by Step-構(gòu)建自己的ORM系列-開篇這篇中的反射的思想,大家可以看看

  特性+反射的思路,我這里的數(shù)據(jù)持久化訪問器也是類似的操作,可能底層的實(shí)現(xiàn)就是這樣的方式。

  具體的數(shù)據(jù)持久化訪問器如何動(dòng)態(tài)的生成SQL語(yǔ)句,緩存優(yōu)化等各方面的內(nèi)容,我們本篇可能不會(huì)深入的講解,我還是想將這塊放在ORM系類篇深入講解。

  當(dāng)然我們其實(shí)可能極端的做飯就是為每個(gè)領(lǐng)域模型中的對(duì)象建立一個(gè)數(shù)據(jù)持久化映射器,完成映射,我這里則是通過創(chuàng)建數(shù)據(jù)庫(kù)的統(tǒng)一模式,在具體的映射器中,

  通過反射取得數(shù)據(jù)對(duì)象的映射信息。我們來看看實(shí)現(xiàn)的思路吧,具體代碼我就不貼了

大體的流程就是上面說的了,細(xì)節(jié)肯定還有很多要注意的地方。

  下面我們來看看查詢服務(wù)的實(shí)現(xiàn):

  我想一般的系統(tǒng)80%的時(shí)間數(shù)據(jù)庫(kù)執(zhí)行的操作是查詢,而20%的時(shí)間在完成寫入和修改的操作,當(dāng)然我這里不是絕對(duì)的說法。我們希望有一個(gè)工具幫我們自動(dòng)完

  成基本的查詢服務(wù),而不是我們手動(dòng)的去書寫,因?yàn)槲覀儼l(fā)現(xiàn)對(duì)大部分的數(shù)據(jù)集合而言,有一些共性的操作,例如獲取某個(gè)主鍵值的對(duì)象的信息,或者是獲取數(shù)據(jù)庫(kù)表

  中的總行數(shù),或者是返回?cái)?shù)據(jù)庫(kù)表的所有記錄,并且如何將關(guān)系數(shù)據(jù)庫(kù)中的關(guān)系模型轉(zhuǎn)換為對(duì)象模型,這都是查詢服務(wù)中應(yīng)該提供的基本功能。下面我們來看看簡(jiǎn)單實(shí)

  現(xiàn)吧。

  我想我們還是參考前面的方式,我們將IDALInterface層中的查詢服務(wù)進(jìn)行抽象分離,將查詢服務(wù)單獨(dú)提出來放在接口IQuery中。代碼如下:

 
 
 
 
  1.   public interface IQuery
  2.   {
  3.   /// 
  4.   /// 查詢所有記錄
  5.   /// 
  6.   /// 泛型模型
  7.   /// 
  8.  IList GetAll() where T : class,new();
  9.   /// 
  10.   /// 查詢滿足條件的集合
  11.   /// 
  12.   /// 
  13.   /// 
  14.   /// 
  15.   IList GetListByQuery(WhereCondition whereCondition) where T : class,new();
  16.   /// 
  17.   /// 返回總行數(shù)
  18.   /// 
  19.   /// 
  20.   /// 
  21.  int GetCount();
  22.   /// 
  23.   /// 返回滿足條件的總行數(shù)
  24.   /// 
  25.   /// 
  26.   /// 
  27.   /// 
  28.   int GetCount(WhereCondition whereCondition);
  29.   /// 
  30.   /// 根據(jù)主鍵返回對(duì)象模型
  31.   /// 
  32.   /// 
  33.   /// 
  34.   /// 
  35.   T GetModelByKey(object key) where T : class,new();
  36.  }

  我們來看看在基類中的實(shí)現(xiàn)。查詢服務(wù)的相關(guān)實(shí)現(xiàn)

 
 
 
 
  1.   /// 
  2.   /// 查詢服務(wù)組件
  3.   /// 
  4.   /// 
  5.   protected abstract IQuery GetQuery();
  6.   #region IQuery 成員
  7.   /// 
  8.   /// 查詢所有記錄
  9.   /// 
  10.   /// 泛型模型
  11.   /// 
  12.   public IList GetAll() where T : class,new()
  13.   {
  14.   return GetQuery().GetAll();
  15.   }
  16.   /// 
  17.  /// 查詢滿足條件的集合
  18.   /// 
  19.   /// 
  20.   /// 
  21.   /// 
  22.   public IList GetListByQuery(WhereCondition whereCondition) where T : class,new()
  23.   {
  24.   return GetQuery().GetAll();
  25.   }
  26.   /// 
  27.   /// 返回總行數(shù)
  28.   /// 
  29.   /// 
  30.   /// 
  31.   public int GetCount()
  32.  {
  33.   return GetQuery().GetCount();
  34.   }
  35.   /// 
  36.   /// 返回滿足條件的總行數(shù)
  37.   /// 
  38.   /// 
  39.   /// 
  40.   /// 
  41.   public int GetCount(WhereCondition whereCondition)
  42.   {
  43.  return GetQuery().GetCount(whereCondition);
  44.   }
  45.   /// 
  46.   /// 根據(jù)主鍵返回對(duì)象模型
  47.   /// 
  48.   /// 
  49.   /// 
  50.   /// 
  51.   public T GetModelByKey(object key) where T : class,new()
  52.   {
  53.   return GetQuery().GetModelByKey(key);
  54.   }
  55.   #endregion

  當(dāng)然根據(jù)不同的數(shù)據(jù)庫(kù)可能定義的查詢語(yǔ)句的格式不同,但是返回的結(jié)果的形式卻可以定義成通用的形式。這樣我們就可以實(shí)現(xiàn)比較通用的查詢服務(wù),也有很好

  的通用型和擴(kuò)展性。當(dāng)然我們這里還可以添加分頁(yè)的支持等,只是添加的條件有限制,實(shí)現(xiàn)方式還是相同。

  下面我們來看看數(shù)據(jù)訪問層功能必須職責(zé)之事務(wù)性,我們都知道事務(wù)性的幾大特性,通過事務(wù)性來提供數(shù)據(jù)的安全性。我們這里給出一種思路去實(shí)現(xiàn)這樣的事務(wù)

  性,我們?cè)跀?shù)據(jù)訪問層中定義一組事務(wù)單元,通過一個(gè)列表維護(hù)這些事務(wù)單元,當(dāng)執(zhí)行提交時(shí),我們將這個(gè)事務(wù)范圍內(nèi)的所有事務(wù)單元進(jìn)行提交,否則不進(jìn)行真正的提

  交操作。我們來看看吧,我們?cè)谥暗腎DALInterface中已經(jīng)定義了事務(wù)相關(guān)的幾個(gè)方法,我們這里同樣抽出來,進(jìn)行分解,抽出來一個(gè)單獨(dú)的接口ITransation,具體

  代碼如下:

 
 
 
 
  1.   public interface ITransaction
  2.   {
  3.   /// 
  4.   /// 是否事務(wù)執(zhí)行
  5.   /// 
  6.   bool IsTransaction
  7.   {
  8.   get;
  9.  }
  10.   /// 
  11.   /// 開始事務(wù)
  12.   /// 
  13.   void BeginTransaction();
  14.   /// 
  15.   /// 提交事務(wù)
  16.   /// 
  17.   void Commit();
  18.   /// 
  19.   /// 回滾事務(wù)
  20.   /// 
  21.  void Rollback();
  22.   }

  基類中的代碼如下:

 
 
 
 
  1.   #region ITransaction
  2.   /// 
  3.   /// 是否事務(wù)執(zhí)行
  4.   /// 
  5.   public bool IsTransaction
  6.   {
  7.   get
  8.   {
  9.   return GetTransaction().IsTransaction;
  10.   }
  11.   }
  12.   /// 
  13.   /// 開始事務(wù)
  14.   /// 
  15.   public void BeginTransaction()
  16.   {
  17.   GetTransaction().BeginTransaction();
  18.   }
  19.   /// 
  20.   /// 提交事務(wù)
  21.   /// 
  22.  public void Commit()
  23.   {
  24.   GetTransaction().Commit();
  25.   }
  26.   /// 
  27.   /// 回滾事務(wù)
  28.   /// 
  29.   public void Rollback()
  30.   {
  31.   GetTransaction().Rollback();
  32.  }
  33.   /// 
  34.   /// 返回事務(wù)單元列表
  35.   /// 
  36.   List list
  37.   {
  38.   get;
  39.   }
  40.   /// 
  41.   /// 執(zhí)行事務(wù)單元的操作,執(zhí)行數(shù)據(jù)操作并提交
  42.   /// 
  43.   /// 
  44.   void Excute(TransationUnit unit);
  45.   #endregion
  46.   /// 
  47.   /// 事務(wù)組件服務(wù)
  48.   /// 
  49.   /// 
  50.  protected abstract ITransaction GetTransaction();

  事務(wù)組件中添加了特殊的事務(wù)單元,用來存儲(chǔ)事務(wù)執(zhí)行的操作CUD,還有就是要事務(wù)執(zhí)行的數(shù)據(jù)對(duì)象,當(dāng)然事務(wù)對(duì)象中的CRD操作就是使用前面講解的CRD操作

  的方式,我們來看看吧,我們來看看事務(wù)單元的形式。

 
 
 
 
  1.   /// 
  2.   /// 事務(wù)單元
  3.   /// 
  4.   public class TransationUnit
  5.   {
  6.  /// 
  7.   /// CUD枚舉
  8.   /// 
  9.   public enum CUDEnum
  10.   {
  11.   Create,
  12.   Update,
  13.   Delete
  14.   }
  15.   private CUDEnum _cudType;
  16.   private object _model;
  17.   public TransationUnit(object model, CUDEnum cudType)
  18.   {
  19.   _model = model;
  20.   _cudType = cudType;
  21.   }
  22.   }

  我們?cè)谑聞?wù)處理中,我們只執(zhí)行事務(wù)列表中的操作,置于非事務(wù)列表中的單元我們將不做任何處理,所以我們只要是事務(wù)執(zhí)行的事務(wù)單元,我們必須將指定操作類

  型,當(dāng)然我們還可以更靈活,我們通過在事務(wù)單元中設(shè)置屬性判定是否在事務(wù)中,如果不在事務(wù)中,我
當(dāng)前文章:系統(tǒng)架構(gòu)師談企業(yè)應(yīng)用架構(gòu)之?dāng)?shù)據(jù)訪問層
文章起源:http://www.dlmjj.cn/article/coojsip.html