新聞中心
一、上章回顧

創(chuàng)新互聯(lián)專注于北屯網(wǎng)站建設(shè)服務(wù)及定制,我們擁有豐富的企業(yè)做網(wǎng)站經(jīng)驗。 熱誠為您提供北屯營銷型網(wǎng)站建設(shè),北屯網(wǎng)站制作、北屯網(wǎng)頁設(shè)計、北屯網(wǎng)站官網(wǎng)定制、微信小程序定制開發(fā)服務(wù),打造北屯網(wǎng)絡(luò)公司原創(chuàng)品牌,更為您提供北屯網(wǎng)站排名全網(wǎng)營銷落地服務(wù)。
上篇我們簡單講述了服務(wù)層架構(gòu)模式中的幾種,并且講解了服務(wù)層的作用及相關(guān)的設(shè)計規(guī)范,其實我們應(yīng)該知道,在業(yè)務(wù)邏輯層中使用領(lǐng)域模型中使用服務(wù)層才
能發(fā)揮出***的優(yōu)勢,如果說我們在業(yè)務(wù)邏輯層還是使用非領(lǐng)域模型的模式話,服務(wù)層的作用僅體現(xiàn)在解耦作用。其實在業(yè)務(wù)邏輯層采用領(lǐng)域模型時,我們前面說的持
久化透明的技術(shù),其實我們可以通過服務(wù)層來做,我們在服務(wù)層中處理領(lǐng)域?qū)ο笮畔⒌某志没僮鳌.?dāng)然本篇可能不會深入討論持久化透明的具體實現(xiàn),后面會單獨開
篇來講述,我們先來回顧下上篇講解的內(nèi)容:
上圖大概描述了上篇我們講解的內(nèi)容,如果您想要詳細(xì)的了解服務(wù)
層的相關(guān)內(nèi)容,請參考:系統(tǒng)架構(gòu)師-基礎(chǔ)到企業(yè)應(yīng)用架構(gòu)-服務(wù)層,后續(xù)我們將會對一些前端的服務(wù)層還會進行擴展的講解,請大家提出報告意見和建議。
二、摘要
本篇將主要以系統(tǒng)中與數(shù)據(jù)庫存儲介質(zhì)進行交互的數(shù)據(jù)訪問層進行詳細(xì)的介紹講解,我想這塊也是大家比較熟悉也是經(jīng)常在項目中一定會用到的部分,我們知道
數(shù)據(jù)訪問層通常我們都把這塊的內(nèi)容提升出來,寫成通用的類庫,在我們前面講解的分層架構(gòu)的系統(tǒng)中,基本上可以說業(yè)務(wù)對象中的數(shù)據(jù)都要通過數(shù)據(jù)訪問層將業(yè)
務(wù)數(shù)據(jù)持久化到存儲介質(zhì)中。其實目前有很多的好的ORM框架已經(jīng)很好的實現(xiàn)了數(shù)據(jù)訪問層,而且得到了很廣泛的應(yīng)用,當(dāng)然我們本篇也會以這些通用的框架為例舉
例說明數(shù)據(jù)訪問層中的一些設(shè)計模式。本章將會以下列幾個典型關(guān)注點展開去講:
1、數(shù)據(jù)訪問層的職責(zé)及與其他組件的交互。
2、如何設(shè)計自己的數(shù)據(jù)訪問層。
3、實現(xiàn)數(shù)據(jù)訪問層必須滿足的4個基本要求,持久化CRUD、查詢服務(wù)、事務(wù)服務(wù)、實現(xiàn)并發(fā)等。
4、結(jié)合目前流行的幾類框架分析框架提供的數(shù)據(jù)訪問層功能的優(yōu)劣。
下面我們將針對上面的幾個關(guān)注點依次展開去說,希望能通過本文的講解,讓您對數(shù)據(jù)庫訪問層有個更深刻的認(rèn)識和了解。
三、本章大綱
1、上章回顧。
2、摘要。
3、本章大綱。
4、數(shù)據(jù)訪問層介紹。
5、如何設(shè)計數(shù)據(jù)訪問層。
6、實現(xiàn)數(shù)據(jù)訪問的四項原則。
7、本章總結(jié)。
8、系列進度。
9、下篇預(yù)告。
四、數(shù)據(jù)庫訪問層簡介
本節(jié)將會主要針對數(shù)據(jù)訪問層的功能及職責(zé)進行講解,分析之前在業(yè)務(wù)邏輯層中的四種模式與數(shù)據(jù)訪問層之間的關(guān)系。我們閑來看看數(shù)據(jù)訪問層與業(yè)務(wù)邏輯層中的
四種模式之間的關(guān)系。
我們在本節(jié)中的講解主要是以領(lǐng)域模型為例進行分析講解,因為只有領(lǐng)域模型模式,我們才能將數(shù)據(jù)訪問層抽離出來,分成單獨的層,這樣能夠做到領(lǐng)域?qū)ο蟪志?/p>
化透明。接下來我們來看看數(shù)據(jù)訪問層都需要提供什么要的功能及數(shù)據(jù)訪問層本身的職責(zé)是什么。
數(shù)據(jù)庫訪問層是唯一知道如何操作存儲介質(zhì)的入口,可以這么來說,基于數(shù)據(jù)訪問層之上,我們調(diào)用數(shù)據(jù)庫訪問層提供的方法,我們就能完成數(shù)據(jù)的存儲與讀取,
所以我們可以知道,數(shù)據(jù)訪問層應(yīng)該是與數(shù)據(jù)庫直接是獨立的。還有就是我們的數(shù)據(jù)訪問層如何能實現(xiàn)不同類型的數(shù)據(jù)庫的動態(tài)的切換,而我們不需要修改任何的程序
功能等,可能我們在開發(fā)的過程中都會遇到這樣的問題。所以我們希望可以對數(shù)據(jù)訪問層完成動態(tài)的配置,通過不同的配置項完成對象數(shù)據(jù)庫訪問的切換,這里我想大
家都是比較熟悉的,通過XML配置文件來完成數(shù)據(jù)庫的切換,前面我們說了我們的需求,是必須實現(xiàn)無縫的數(shù)據(jù)庫的切換,那么我們?nèi)绾螌崿F(xiàn)呢,這里我們可以通過定
義一個數(shù)據(jù)庫訪問接口,然后通過實現(xiàn)不同的數(shù)據(jù)庫的細(xì)節(jié),來實現(xiàn)這樣的切換。目前很多流行的框架都是采用這樣的方式來實現(xiàn)數(shù)據(jù)庫的動態(tài)切換。當(dāng)然有時候我們
的項目中肯能不讓我們使用開源的通用框架,這時候我們可能就需要自己去實現(xiàn)這些數(shù)據(jù)訪問層的具體細(xì)節(jié)。
當(dāng)然數(shù)據(jù)訪問層都必須能夠?qū)?yīng)用程序中的數(shù)據(jù)持久化到存儲介質(zhì)中,通常我們使用的數(shù)據(jù)都是關(guān)系型的數(shù)據(jù)庫,但是我們知道我們在程序的開發(fā)中,通常采用的
模型都是對象模型,那么如何實現(xiàn)對象模型與關(guān)系模型直接的互相的轉(zhuǎn)換就顯得非常的重要。當(dāng)然這是數(shù)據(jù)訪問層的重要功能。通常來說,業(yè)務(wù)邏輯層及服務(wù)層不了解
數(shù)據(jù)庫訪問的具體細(xì)節(jié),他們都需要通過數(shù)據(jù)訪問層來實現(xiàn)數(shù)據(jù)的交互。一般來說在領(lǐng)域模型中,數(shù)據(jù)訪問通常都是在服務(wù)層中進行調(diào)用的,而業(yè)務(wù)邏輯層并不關(guān)注數(shù)
據(jù)持久化,所以我們前面說的持久化透明的方式也是由此方式來實現(xiàn)。
上面我們啰嗦了一大堆,基本上說了數(shù)據(jù)訪問層的基本需求功能:
下面我們來看看數(shù)據(jù)訪問層的幾個基本職責(zé)
首先、數(shù)據(jù)訪問層應(yīng)該提供基本的持久化操作CRUD的操作,我們知道數(shù)據(jù)訪問層是唯一能操作數(shù)據(jù)庫的一層,因為我們在設(shè)計時需要注意,系統(tǒng)的其他層不能
包含操作數(shù)據(jù)庫的相關(guān)功能
這里我們通過類圖可以看到,通過提供與類對應(yīng)的數(shù)據(jù)庫操作類來提供
相應(yīng)的持久化操作方法,當(dāng)然這不是唯一方式,可行的方式有很多。我們后面會詳細(xì)討論。
其次、應(yīng)該提供能夠滿足類中信息的讀取操作,一般情況下來說我們經(jīng)常使用的是,根據(jù)主鍵查詢某個對象的信息,或者是查詢所有的記錄,或者是根據(jù)條件返
回滿足的集合。
當(dāng)然我們這里定義的查詢類可能是通用的形式,通過泛型的形式來做。但是我們知道
領(lǐng)域模型中肯定會有引用對象的情況,那么對于這樣的情況我們?nèi)绾蝸碜瞿兀课覀円话闶峭ㄟ^延遲加載的形式來處理這樣的要求,我們后面會依次講解。我們來看看上
面的通用形式的簡單代碼格式:
- public class QueryHelper
- {
- ///
- /// 根據(jù)主鍵返回對象
- ///
- ///
- ///
- ///
- public T GetObjectByKey
(object key) - {
- return default(T);
- }
- ///
- /// 獲取指定類型對象的總記錄數(shù)
- ///
- ///
- ///
- ///
- public int GetCount
(object key) - {
- return 0;
- }
- ///
- /// 返回指定類型的所有對象集合
- ///
- ///
- ///
- public List
GetAll () - {
- return new List
(); - }
- }
再次、數(shù)據(jù)庫訪問必須提供事務(wù)的管理,可以說不提供事務(wù)操作的數(shù)據(jù)訪問層就沒有辦法使用,因為這樣的數(shù)據(jù)訪問層構(gòu)建的系統(tǒng)是不安全的。特別是批量持久
化的過程中,事務(wù)不但能夠減少與數(shù)據(jù)庫操作的次數(shù),而且根據(jù)事務(wù)的四個特性可以提供更好的安全性。我們來回顧下事務(wù)的四個特性:
我想我這里就不用一一解釋了,大家都明白的。我們在數(shù)據(jù)訪問層的設(shè)計中是通過引入
“工作單元”來實現(xiàn)事務(wù)管理的,工作單元后面會講述到工作單元內(nèi)提供的方法及事務(wù)性。
***、數(shù)據(jù)訪問層必須提供處理并發(fā)的功能,我們在系統(tǒng)訪問的人較多的情況時肯定會出現(xiàn)并發(fā)的情況,數(shù)據(jù)訪問層如何處理這樣的情況就顯得極其重要了,在
一個多用戶并發(fā)的系統(tǒng)中,通過前面提到的事務(wù)來處理,這時候可能就會出現(xiàn)數(shù)據(jù)庫完整性的問題,例如這樣的情況,一個用戶現(xiàn)在在編輯自己的個人信息,例如將生
日修改為1985年3月20日,這個用戶對應(yīng)的ID是298,這時候他只是修改了,但是還沒有提交,此時管理員也修改了,比如說修改了ID為298的這個用戶信息的地址或
者其他信息,并且提交,此時,用戶將自己編輯的生日提交了,那么數(shù)據(jù)庫中對應(yīng)的ID為298的數(shù)據(jù)信息就會是***修改的數(shù)據(jù)信息,那么之前管理員修改的數(shù)據(jù)信息
就會發(fā)生丟失,雖然是修改的可能字段不是同一個字段,這就和我們底層實現(xiàn)的數(shù)據(jù)訪問層有關(guān),當(dāng)然如果說我們在數(shù)據(jù)訪問層實現(xiàn)了,只更新修改過的數(shù)據(jù)列的值的
話,那么可能不會存在這樣的情況,當(dāng)然這就和我們底層實現(xiàn)的數(shù)據(jù)訪問層的機制有關(guān)。
下面我們通過圖形的方式來說明,更容易理解:
我們來看看可能的幾種方案,可以對這樣的并發(fā)做出相應(yīng)的處理?
當(dāng)然這里只是提供了幾個簡單可行的辦法,當(dāng)然如果大家還
有更好的辦法,可以告訴我,不勝感激。
當(dāng)然上面的四個基本職責(zé)是我們在數(shù)據(jù)訪問層必須提供的,還應(yīng)該提供緩存機制,延遲加載等等包括一些性能方面的優(yōu)化的設(shè)計等,這些都在后面講解吧。
下面我們來看看數(shù)據(jù)訪問層與其他層直接的關(guān)系與交互,我們前面說過,在領(lǐng)域模型下,業(yè)務(wù)邏輯層中的數(shù)據(jù)的持久化都是通過服務(wù)層來完成的,下面我們來看
看各層之間的關(guān)系。我們先來看看服務(wù)層與數(shù)據(jù)訪問層之間的關(guān)系。
服務(wù)層與數(shù)據(jù)訪問層之間進行交互,服務(wù)層通過DTO與UI層進行交互,服務(wù)層通過組織業(yè)務(wù)邏輯層中的對象來實
現(xiàn)業(yè)務(wù)流,然后通過調(diào)用數(shù)據(jù)訪問層將業(yè)務(wù)流中的相應(yīng)數(shù)據(jù)進行持久化,通過數(shù)據(jù)訪問層來初始化領(lǐng)域模型。置于直接在表現(xiàn)層中使用數(shù)據(jù)訪問層的功能,我們通常是
不推薦這樣做的,一般我們不會這么做的,我這里就不詳細(xì)的闡述。
五、如何設(shè)計數(shù)據(jù)訪問層
本節(jié)將詳細(xì)的講述如何設(shè)計出自己的數(shù)據(jù)訪問層,滿足上述的幾個基本要求,那么可以說就算完成了基本的數(shù)據(jù)訪問層的功能,其實如果我們從頭開始開發(fā)一個
這樣的數(shù)據(jù)訪問層將是非常大的工作量,目前流行的很多的ORM框架已經(jīng)提供了豐富的數(shù)據(jù)訪問層的功能,能夠非常好的滿足上述的幾項職責(zé)。當(dāng)然本節(jié)還是會結(jié)合代
碼來說說數(shù)據(jù)訪問層的具體實現(xiàn)。
我們前面講述了數(shù)據(jù)訪問的3個基本的功能需求,數(shù)據(jù)庫獨立性,可配置性及持久化對象模式(對象模型與關(guān)系模型的轉(zhuǎn)換),我們這里先看如何實現(xiàn)數(shù)據(jù)庫的獨立
性,我們提出滿足數(shù)據(jù)庫的無縫遷移,通過XML配置文件,配置不同的數(shù)據(jù)庫鏈接來實現(xiàn)這樣的功能,那么首先我們需要定義針對不同數(shù)據(jù)庫具體實現(xiàn),才能完成后續(xù)
的操作,既然我們這里要降低耦合,那么根據(jù)我們前面的面向?qū)ο蟮脑O(shè)計原則與規(guī)范知道,我們推薦使用面向接口的編程的方式,來盡量的降低耦合性。我們來看看具
體的代碼。首先我們定義一個通用的數(shù)據(jù)訪問層的接口。
- ///
- /// 數(shù)據(jù)訪問層統(tǒng)一接口
- ///
- public interface IDALInterface
- {
- //CUD 持久化操作
- ///
- /// 創(chuàng)建新的對象
- ///
- ///
- ///
- int Create(object model);
- ///
- /// 更新對象
- ///
- ///
- ///
- int Update(object model);
- ///
- /// 刪除對象
- ///
- ///
- ///
- int Delete(object model);
- //R 查詢服務(wù)
- ///
- /// 查詢所有記錄
- ///
- ///
泛型模型 - ///
- IList
GetAll () where T : class,new(); - ///
- /// 查詢滿足條件的集合
- ///
- ///
- ///
- ///
- IList
GetListByQuery (WhereCondition whereCondition) where T : class,new(); - ///
- /// 返回總行數(shù)
- ///
- ///
- ///
- int GetCount
(); - ///
- /// 返回滿足條件的總行數(shù)
- ///
- ///
- ///
- ///
- int GetCount
(WhereCondition whereCondition); - ///
- /// 根據(jù)主鍵返回對象模型
- ///
- ///
- ///
- ///
- T GetModelByKey
(object key) where T : class,new(); - //事務(wù)
- ///
- /// 是否事務(wù)執(zhí)行
- ///
- bool IsTransaction
- {
- get;
- }
- ///
- /// 開始事務(wù)
- ///
- void BeginTransaction();
- ///
- /// 提交事務(wù)
- ///
- void Commit();
- ///
- /// 回滾事務(wù)
- ///
- void Rollback();
- }
這里定義了基本的幾個簡單方法,當(dāng)然其中并沒有包括并發(fā)的處理,后面會講到這塊的處理方案的實現(xiàn), 前面介紹了幾種可行的實現(xiàn)方式。接口定義好了之后,
數(shù)據(jù)層的具體代碼我這里就不一一的定義貼出來了,因為每種不同的數(shù)據(jù)庫類型就要分別實現(xiàn),我們這里講解2中不同類型的實現(xiàn)思路吧,
我們這里講解2中實現(xiàn)動態(tài)創(chuàng)建具體數(shù)據(jù)訪問組件的方式,我們先來講講插件模式。
插件模式
插件模式:插件模式就是通過外部配置文件中讀取要創(chuàng)建的組件的類型信息,然后調(diào)用組件服務(wù),插件模式的關(guān)鍵點就是服務(wù)不會與具體實現(xiàn)聯(lián)系起來,在我們的
分層結(jié)構(gòu)中的解釋就是,服務(wù)層中調(diào)用數(shù)據(jù)訪問層中的組件服務(wù),服務(wù)層不關(guān)系具體的調(diào)用方式,服務(wù)層只關(guān)心服務(wù)。而具體的數(shù)據(jù)訪問組件是通過配置文件來動態(tài)的
創(chuàng)建,當(dāng)然這就需要使用.NET中的反射的功能。我們來看個圖形畫的描述:
反射工廠通過讀取配置文件中具體的數(shù)據(jù)配置項及數(shù)據(jù)訪問的具
體服務(wù)組件類型,通過反射工廠來動態(tài)的創(chuàng)建,好了我們來看看實例代碼及配置文件。
- value="Data Source=.SQLEXPRESS;Initial Catalog=EasyStore;User ID=sa;Password=123456" />
- value="Data Source=.SQLEXPRESS;Initial Catalog=EasyStore;User ID=sa;Password=123456" />
- value="DAL.SQLServer" /> value="DAL.SQLServer" />
- value="DAL.SQLServer" /> value="DAL.SQLServer" />
上面的配置文件中的ConnectionItem 節(jié)點中配置了數(shù)據(jù)庫訪問的鏈接字符串,DALType 定義了數(shù)據(jù)訪問層組件的類型。我們下來看看反射工廠的示例代碼實
現(xiàn)。
- public class DALHelper
- {
- private static IDALInterface instance;
- public static IDALInterface GetDAL()
- {
- string assambly = XmlHelper.getVlaue("Assembly");//這里應(yīng)該是自定義的讀取XML節(jié)點的方式
- string type = XmlHelper.getVlaue("DALType");
- Assembly asm = Assembly.Load(assambly);
- instance = (IDALInterface)asm.CreateInstance(type);
- return instance;
- }
- }
我們接下來看看如何使用這個數(shù)據(jù)訪問層去實現(xiàn)相應(yīng)的持久化操作:
- public class TestService
- {
- private IDALInterface DAL;
- public TestService()
- {
- DAL = DALHelper.GetDAL();
- }
- public void Create(Test test)
- {
- //相應(yīng)的判定操作
- //創(chuàng)建對象
- DAL.Create(test);
- }
- }
這樣就實現(xiàn)了在服務(wù)層對數(shù)據(jù)訪問層的調(diào)用操作,這里是通過接口調(diào)用的方式來實現(xiàn)。我們再來看看控制反轉(zhuǎn)的實現(xiàn)方式吧。
控制反轉(zhuǎn)
控制反轉(zhuǎn)我們在設(shè)計規(guī)范與原則中有過講解,控制反正通過動態(tài)的將組件注入到引用該組件的對象中的形式,然后讓引用該組件的對象使用組件的服務(wù),DI依賴注
入可以看作是控制反轉(zhuǎn)的一個應(yīng)用實例,我們可以把控制反轉(zhuǎn)看作是一個原則。
下面我們來看看我們?nèi)绾瓮ㄟ^控制反正的方式來實現(xiàn)數(shù)據(jù)訪問層的平滑遷移。當(dāng)然我們知道,肯定是通過動態(tài)注入的方式來實現(xiàn),當(dāng)然目前主流的也有很多的IOC動
態(tài)注入框架,下面我們將會借助一些框架來說明如何實現(xiàn)這樣的功能。
本文將以Enterprise Library5.0為例進行講解動態(tài)注入的形式。我們先來看看配置文件的設(shè)置
我們來看看通過一個中間類去實現(xiàn)相應(yīng)的注冊代碼:
- ///
- /// 用于動態(tài)完成代碼注入的公共類
- ///
- public class IOCContainer
- {
- private static IUnityContainer container;
- private UnityConfigurationSection section;
- public void InitIOC()
- {
- container = new UnityContainer();
- section = (UnityConfigurationSection)System.Configuration.ConfigurationManager.GetSection("unity");
- section.Configure(container);
- }
- public static IDALInterface GetDAL()
- {
- return container.Resolve
(); - }
- }
通過上述代碼我們實現(xiàn)了,動態(tài)的創(chuàng)建數(shù)據(jù)訪問層組件實例,下面我們來看看依賴注入的方式去完成相應(yīng)的持久化的功能。我們來看看服務(wù)層的代碼
- ///
- /// 測試服務(wù)層
- ///
- public class TestService
- {
- private IDALInterface DAL;
- public TestService(IDALInterface dal)
- {
- DAL = dal;
- }
- public void Save(Test test)
- {
- DAL.Create(test);
- }
- }
這里我們是采用構(gòu)造函數(shù)注入的方式來實現(xiàn)數(shù)據(jù)訪問層的動態(tài)注入的,當(dāng)然除了構(gòu)造函數(shù)注入,還有其他的方式,我們這里只是舉例說明,一般來說依賴注入有
如下的幾種形式
具體的我這里就不舉例說明了,大家可以網(wǎng)上查查有很多的例
子,我們平時也常用這些方式。
六、實現(xiàn)數(shù)據(jù)訪問的四項原則
在第四節(jié)中我們講解了數(shù)據(jù)訪問層的四個原則,那么我們在自己的數(shù)據(jù)訪問層中如何實現(xiàn)這幾個原則呢,我想針對***個原則持久化的原則,我們前面只是簡單
的講解如何實現(xiàn)數(shù)據(jù)庫的獨立性,下面我們先來看看持久化的操作,也就是我們說的CUD的操作,并不包括具體的查詢服務(wù),查詢服務(wù)也是我們數(shù)據(jù)訪問層必須提供四
個原則之一,我們后面都會講解,我們先來看看CUD的實現(xiàn)。我們在做持久化服務(wù)的時候,一般情況下,我們會定義一個統(tǒng)一的數(shù)據(jù)訪問層接口,然后提供持久化服
務(wù),事務(wù)等等,通常有一些數(shù)據(jù)訪問層共性的部分,我們都通過一個抽象類來實現(xiàn),抽象類將實現(xiàn)接口中的部分功能,然后通過定義一些抽象成員函數(shù),讓具體的數(shù)據(jù)
訪問層去實現(xiàn)相應(yīng)的功能。我們這里以上節(jié)我們定義的IDALInterface為例講解基類的簡單實現(xiàn)。
我們將原來的接口層進行相關(guān)的優(yōu)化操作將CUD操作單獨抽取出來,通過ICUDMapper接口來定義
- ///
- /// 數(shù)據(jù)庫持久化訪問器
- ///
- public interface ICUDMapper
- {
- //CUD 持久化操作
- ///
- /// 創(chuàng)建新的對象
- ///
- ///
- ///
- int Create(object model);
- ///
- /// 更新對象
- ///
- ///
- ///
- int Update(object model);
- ///
- /// 刪除對象
- ///
- ///
- ///
- int Delete(object model);
- }
然后我們來看看基類接口層的簡單實現(xiàn),作為所有數(shù)據(jù)訪問層的父類
- public abstract class BaseDAL : IDALInterface,IDisposable
- {
- protected abstract ICUDMapper GetMapper();
- //CUD 持久化操作
- ///
- /// 創(chuàng)建新的對象
- ///
- ///
- ///
- public int Create(object model)
- {
- return GetMapper().Create(model);
- }
- ///
- /// 更新對象
- ///
- ///
- ///
- public int Update(object model)
- {
- return GetMapper().Update(model);
- }
- ///
- /// 刪除對象
- ///
- ///
- ///
- public int Delete(object model)
- {
- return GetMapper().Delete(model);
- }
- #region IDisposable 成員
- ///
- /// 是否數(shù)據(jù)庫訪問組件資源
- ///
- public void Dispose()
- {
- }
- #endregion
- }
當(dāng)然這里只貼出實例代碼。當(dāng)然我采用這樣的方式,就是利用我們之前的一篇:Step by Step-構(gòu)建自己的ORM系列-開篇這篇中的反射的思想,大家可以看看
特性+反射的思路,我這里的數(shù)據(jù)持久化訪問器也是類似的操作,可能底層的實現(xiàn)就是這樣的方式。
具體的數(shù)據(jù)持久化訪問器如何動態(tài)的生成SQL語句,緩存優(yōu)化等各方面的內(nèi)容,我們本篇可能不會深入的講解,我還是想將這塊放在ORM系類篇深入講解。
當(dāng)然我們其實可能極端的做飯就是為每個領(lǐng)域模型中的對象建立一個數(shù)據(jù)持久化映射器,完成映射,我這里則是通過創(chuàng)建數(shù)據(jù)庫的統(tǒng)一模式,在具體的映射器中,
通過反射取得數(shù)據(jù)對象的映射信息。我們來看看實現(xiàn)的思路吧,具體代碼我就不貼了
大體的流程就是上面說的了,細(xì)節(jié)肯定還有很多要注意的地方。
下面我們來看看查詢服務(wù)的實現(xiàn):
我想一般的系統(tǒng)80%的時間數(shù)據(jù)庫執(zhí)行的操作是查詢,而20%的時間在完成寫入和修改的操作,當(dāng)然我這里不是絕對的說法。我們希望有一個工具幫我們自動完
成基本的查詢服務(wù),而不是我們手動的去書寫,因為我們發(fā)現(xiàn)對大部分的數(shù)據(jù)集合而言,有一些共性的操作,例如獲取某個主鍵值的對象的信息,或者是獲取數(shù)據(jù)庫表
中的總行數(shù),或者是返回數(shù)據(jù)庫表的所有記錄,并且如何將關(guān)系數(shù)據(jù)庫中的關(guān)系模型轉(zhuǎn)換為對象模型,這都是查詢服務(wù)中應(yīng)該提供的基本功能。下面我們來看看簡單實
現(xiàn)吧。
我想我們還是參考前面的方式,我們將IDALInterface層中的查詢服務(wù)進行抽象分離,將查詢服務(wù)單獨提出來放在接口IQuery中。代碼如下:
- public interface IQuery
- {
- ///
- /// 查詢所有記錄
- ///
- ///
泛型模型 - ///
- IList
GetAll () where T : class,new(); - ///
- /// 查詢滿足條件的集合
- ///
- ///
- ///
- ///
- IList
GetListByQuery (WhereCondition whereCondition) where T : class,new(); - ///
- /// 返回總行數(shù)
- ///
- ///
- ///
- int GetCount
(); - ///
- /// 返回滿足條件的總行數(shù)
- ///
- ///
- ///
- ///
- int GetCount
(WhereCondition whereCondition); - ///
- /// 根據(jù)主鍵返回對象模型
- ///
- ///
- ///
- ///
- T GetModelByKey
(object key) where T : class,new(); - }
我們來看看在基類中的實現(xiàn)。查詢服務(wù)的相關(guān)實現(xiàn)
- ///
- /// 查詢服務(wù)組件
- ///
- ///
- protected abstract IQuery GetQuery();
- #region IQuery 成員
- ///
- /// 查詢所有記錄
- ///
- ///
泛型模型 - ///
- public IList
GetAll () where T : class,new() - {
- return GetQuery().GetAll
(); - }
- ///
- /// 查詢滿足條件的集合
- ///
- ///
- ///
- ///
- public IList
GetListByQuery (WhereCondition whereCondition) where T : class,new() - {
- return GetQuery().GetAll
(); - }
- ///
- /// 返回總行數(shù)
- ///
- ///
- ///
- public int GetCount
() - {
- return GetQuery().GetCount
(); - }
- ///
- /// 返回滿足條件的總行數(shù)
- ///
- ///
- ///
- ///
- public int GetCount
(WhereCondition whereCondition) - {
- return GetQuery().GetCount
(whereCondition); - }
- ///
- /// 根據(jù)主鍵返回對象模型
- ///
- ///
- ///
- ///
- public T GetModelByKey
(object key) where T : class,new() - {
- return GetQuery().GetModelByKey
(key); - }
- #endregion
當(dāng)然根據(jù)不同的數(shù)據(jù)庫可能定義的查詢語句的格式不同,但是返回的結(jié)果的形式卻可以定義成通用的形式。這樣我們就可以實現(xiàn)比較通用的查詢服務(wù),也有很好
的通用型和擴展性。當(dāng)然我們這里還可以添加分頁的支持等,只是添加的條件有限制,實現(xiàn)方式還是相同。
下面我們來看看數(shù)據(jù)訪問層功能必須職責(zé)之事務(wù)性,我們都知道事務(wù)性的幾大特性,通過事務(wù)性來提供數(shù)據(jù)的安全性。我們這里給出一種思路去實現(xiàn)這樣的事務(wù)
性,我們在數(shù)據(jù)訪問層中定義一組事務(wù)單元,通過一個列表維護這些事務(wù)單元,當(dāng)執(zhí)行提交時,我們將這個事務(wù)范圍內(nèi)的所有事務(wù)單元進行提交,否則不進行真正的提
交操作。我們來看看吧,我們在之前的IDALInterface中已經(jīng)定義了事務(wù)相關(guān)的幾個方法,我們這里同樣抽出來,進行分解,抽出來一個單獨的接口ITransation,具體
代碼如下:
- public interface ITransaction
- {
- ///
- /// 是否事務(wù)執(zhí)行
- ///
- bool IsTransaction
- {
- get;
- }
- ///
- /// 開始事務(wù)
- ///
- void BeginTransaction();
- ///
- /// 提交事務(wù)
- ///
- void Commit();
- ///
- /// 回滾事務(wù)
- ///
- void Rollback();
- }
基類中的代碼如下:
- #region ITransaction
- ///
- /// 是否事務(wù)執(zhí)行
- ///
- public bool IsTransaction
- {
- get
- {
- return GetTransaction().IsTransaction;
- }
- }
- ///
- /// 開始事務(wù)
- ///
- public void BeginTransaction()
- {
- GetTransaction().BeginTransaction();
- }
- ///
- /// 提交事務(wù)
- ///
- public void Commit()
- {
- GetTransaction().Commit();
- }
- ///
- /// 回滾事務(wù)
- ///
- public void Rollback()
- {
- GetTransaction().Rollback();
- }
- ///
- /// 返回事務(wù)單元列表
- ///
- List
list - {
- get;
- }
- ///
- /// 執(zhí)行事務(wù)單元的操作,執(zhí)行數(shù)據(jù)操作并提交
- ///
- ///
- void Excute(TransationUnit unit);
- #endregion
- ///
- /// 事務(wù)組件服務(wù)
- ///
- ///
- protected abstract ITransaction GetTransaction();
事務(wù)組件中添加了特殊的事務(wù)單元,用來存儲事務(wù)執(zhí)行的操作CUD,還有就是要事務(wù)執(zhí)行的數(shù)據(jù)對象,當(dāng)然事務(wù)對象中的CRD操作就是使用前面講解的CRD操作
的方式,我們來看看吧,我們來看看事務(wù)單元的形式。
- ///
- /// 事務(wù)單元
- ///
- public class TransationUnit
- {
- ///
- /// CUD枚舉
- ///
- public enum CUDEnum
- {
- Create,
- Update,
- Delete
- }
- private CUDEnum _cudType;
- private object _model;
- public TransationUnit(object model, CUDEnum cudType)
- {
- _model = model;
- _cudType = cudType;
- }
- }
我們在事務(wù)處理中,我們只執(zhí)行事務(wù)列表中的操作,置于非事務(wù)列表中的單元我們將不做任何處理,所以我們只要是事務(wù)執(zhí)行的事務(wù)單元,我們必須將指定操作類
型,當(dāng)然我們還可以更靈活,我們通過在事務(wù)單元中設(shè)置屬性判定是否在事務(wù)中,如果不在事務(wù)中,我
網(wǎng)頁題目:系統(tǒng)架構(gòu)師談企業(yè)應(yīng)用架構(gòu)之?dāng)?shù)據(jù)訪問層
瀏覽地址:http://fisionsoft.com.cn/article/coojsip.html


咨詢
建站咨詢
