一区二区久久-一区二区三区www-一区二区三区久久-一区二区三区久久精品-麻豆国产一区二区在线观看-麻豆国产视频

Step by Step-構(gòu)建自己的ORM系列-數(shù)據(jù)訪問(wèn)層

一、開(kāi)篇

         距離上篇《Step by Step-構(gòu)建自己的ORM系列-開(kāi)篇》的時(shí)間間隔的太久了,很對(duì)不住大家啊,主要是因?yàn)橛袔讉€(gè)系列必須提前先寫(xiě)完,才能繼續(xù)這個(gè)系列,當(dāng)然我也在

寫(xiě)這幾個(gè)系列的過(guò)程中,對(duì)ORM這個(gè)系列中的原來(lái)的實(shí)現(xiàn)的想法有了新的認(rèn)識(shí)和改進(jìn),當(dāng)然這些都不是說(shuō)是很先進(jìn)的思想或者認(rèn)識(shí),也可能是大家見(jiàn)過(guò)的思路吧,希望后面我能在

寫(xiě)設(shè)計(jì)模式系列的過(guò)程中,穿插講解ORM系列,當(dāng)然我的這個(gè)構(gòu)建的系列,也只能說(shuō)是很簡(jiǎn)易的,自己平時(shí)開(kāi)發(fā)個(gè)小應(yīng)用工具或者什么的,可能用他,因?yàn)槭亲约洪_(kāi)發(fā)的嘛,畢竟

使用起來(lái)還是比較順手的!符合自己的操作習(xí)慣嘛。

        當(dāng)然我寫(xiě)這個(gè)系列的過(guò)程中,也會(huì)有自己認(rèn)識(shí)偏激的地方,或者思路不正確的地方,還請(qǐng)大伙多多指出和批評(píng)。我也是在我目前的項(xiàng)目中學(xué)習(xí)到了很多的寶貴的經(jīng)驗(yàn),其實(shí)

我們應(yīng)該能看到ORM給我們提供的方便和不便之處,我們?nèi)∑渚A,剔除糟粕,不過(guò)這真的很難。我其實(shí)對(duì)一些流行的ORM的底層實(shí)現(xiàn),研究的不多也不深,像Nhibernate,我

只是了解Hibernate,是當(dāng)時(shí)從Java中了解過(guò)來(lái)的,不深入,Castle框架倒是用過(guò)一段時(shí)間,EntityFreamWork,我也沒(méi)有用過(guò),只是象征性的下載最新版本,體驗(yàn)了下AOP的

方式,我感覺(jué)其實(shí)有很多的時(shí)候,我們使用AOP的方式,能夠改進(jìn)我們程序的靈活性。這塊可能還需要大牛們多多指點(diǎn)。

        我理想的ORM是實(shí)現(xiàn)持久化的透明,這個(gè)怎么理解呢?就是說(shuō)我在程序的開(kāi)發(fā)中,我不想在業(yè)務(wù)代碼中書(shū)寫(xiě)相應(yīng)的持久化操作,也不關(guān)心業(yè)務(wù)層中的去如何調(diào)用你的

ORM,去完成CRUD的操作。我只關(guān)心我的業(yè)務(wù)邏輯,這個(gè)有點(diǎn)像DDD(領(lǐng)域驅(qū)動(dòng)開(kāi)發(fā))里面的領(lǐng)域?qū)恿耍魂P(guān)心領(lǐng)域內(nèi)部的業(yè)務(wù)邏輯,而不關(guān)心其他的東西,這樣方便我們快速

的抓住關(guān)注的東西,而盡量讓與領(lǐng)域無(wú)關(guān)的東西不要影響業(yè)務(wù)領(lǐng)域邏輯的實(shí)現(xiàn)。

二、摘要

        本篇主要開(kāi)始講述《Step by Step-構(gòu)建自己的ORM系列-數(shù)據(jù)訪問(wèn)層》關(guān)于數(shù)據(jù)訪問(wèn)層的部分,其實(shí)前面也對(duì)這塊的內(nèi)容有了一定的介紹了,其實(shí)本篇就是教你如何完成

ORM中的數(shù)據(jù)訪問(wèn)層的操作,這里是提供統(tǒng)一的數(shù)據(jù)訪問(wèn)方法的實(shí)現(xiàn)。當(dāng)然這里的操作還是主要集中在數(shù)據(jù)庫(kù)的操作,包括如何根據(jù)實(shí)體對(duì)象返回實(shí)體的列表,包括生成SQL語(yǔ)

句的幾類(lèi)實(shí)現(xiàn),還包括一些實(shí)現(xiàn)后續(xù)的ORM的配置管理的維護(hù),這里就是提供可視化的XML文件的配置,這個(gè)具體怎么來(lái)做呢?因?yàn)槲覀兤綍r(shí)針對(duì)ORM的使用,都是直接修改

XML文件,我們可以提供一個(gè)可視化的界面,讓那個(gè)用戶配置這些相應(yīng)的設(shè)置。通過(guò)這些配置,我們可以實(shí)現(xiàn)數(shù)據(jù)庫(kù)的平滑的遷移,緩存應(yīng)用的配置,包括其他的一些相關(guān)設(shè)置信

息。總體來(lái)說(shuō)這些操作都可以依托于,我們這里的數(shù)據(jù)訪問(wèn)層來(lái)完成。

        我們來(lái)看看ORM中數(shù)據(jù)訪問(wèn)層的重要作用和地位吧:

image

上圖我們知道,我們所有的相關(guān)功能的基礎(chǔ),都是基于數(shù)據(jù)訪問(wèn)層來(lái)做的,所以我們處理好這個(gè)層的相關(guān)邏輯

后,后續(xù)的問(wèn)題就會(huì)比較容易開(kāi)展。下面我們就會(huì)針對(duì)這些疑問(wèn)開(kāi)始

一個(gè)個(gè)的解決我們的數(shù)據(jù)訪問(wèn)層應(yīng)該提供的相關(guān)功能!大體的功能應(yīng)該有如下功能:

1、持久化的操作方法CUD。可以擴(kuò)展提供創(chuàng)建表+其他的修改表等相關(guān)的自動(dòng)腳本工具。提供持久化透明的方式。

2、提供緩存服務(wù),將對(duì)象的相應(yīng)映射信息緩存起來(lái),這樣后續(xù)執(zhí)行生成語(yǔ)句等操作,效率上會(huì)是很大的提升。

3、我們?cè)谔幚韺?duì)象對(duì)于Update語(yǔ)句,應(yīng)該能處理好只能更變化的信息,如果沒(méi)有發(fā)生變化,那么我們是不是不用執(zhí)行更新操作了呢?減少數(shù)據(jù)庫(kù)的操作次數(shù)。

4、提供基礎(chǔ)的查詢方法,以后所有的基于ORM上的查詢基于這個(gè)查詢進(jìn)行擴(kuò)展。提供持久化透明的查詢方式。

5、并發(fā)和事務(wù)的控制。我們這里可能提供一個(gè)內(nèi)部的版本號(hào)的方式來(lái)做,一旦修改過(guò)這個(gè)對(duì)象或者發(fā)生改變,任何時(shí)候的操作,我們都是針對(duì)這個(gè)版本號(hào)的記錄來(lái)做的,版本號(hào)

通過(guò)內(nèi)部提供的方法來(lái)進(jìn)行。

三、本文大綱

       1、開(kāi)篇。

       2、摘要。

       3、本文大綱。

       4、ORM之?dāng)?shù)據(jù)訪問(wèn)層分析。

       5、ORM相關(guān)代碼實(shí)現(xiàn)。

       6、本章總結(jié)。

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

       8、下篇預(yù)告。

四、ORM之?dāng)?shù)據(jù)訪問(wèn)層分析

        我們先來(lái)針對(duì)上面的幾個(gè)問(wèn)題,我們給出實(shí)現(xiàn)思路,來(lái)分析下給出的思路的可行性和如何實(shí)現(xiàn)的解析。具體的代碼下節(jié)給出核心實(shí)現(xiàn)方案。

       4.1、提供通用的持久化的操作

        這個(gè)具體的解析在上篇中已經(jīng)給出了相應(yīng)的思路了,我們通過(guò)在底層提供相應(yīng)的方法來(lái)做。一般來(lái)說(shuō),對(duì)應(yīng)數(shù)據(jù)庫(kù)的四種操作,我們?cè)跀?shù)據(jù)訪問(wèn)層,也提供了相應(yīng)的語(yǔ)句的

自動(dòng)構(gòu)造的過(guò)程,具體的構(gòu)造,我們前面給出的實(shí)現(xiàn)方案是通過(guò)特性來(lái)實(shí)現(xiàn),特性中定義具體的數(shù)據(jù)庫(kù)字段,類(lèi)型,長(zhǎng)度等一些列的參數(shù)。我這里就不復(fù)述了,我這里分析下我們

這樣實(shí)現(xiàn)的好處。我們知道繼承的方式是挺好的,我為什么這么說(shuō),通過(guò)提供一個(gè)基類(lèi),基類(lèi)中定義通用的CUD的操作方法,這樣只要是繼承這個(gè)類(lèi)的子類(lèi),都會(huì)有CUD的操作

方法了,但是我們?yōu)榱颂峁┏志没该鞯姆桨福敲礋o(wú)疑,對(duì)于持久化的操作,我們就不希望由業(yè)務(wù)邏輯層中的業(yè)務(wù)邏輯對(duì)象來(lái)完成,那么如何來(lái)做呢?我們通過(guò)數(shù)據(jù)訪問(wèn)層,提

供統(tǒng)一的操作方法,讓服務(wù)層來(lái)完成業(yè)務(wù)對(duì)象的持久化操作。這樣就能實(shí)現(xiàn),持久化透明的方案。

       所以我們可以這樣來(lái)做,在數(shù)據(jù)訪問(wèn)層中,我們提供一個(gè)接口,接口中定義持久化操作的幾類(lèi)方案,通過(guò)不同的實(shí)現(xiàn)配置,我們可以在XML配置文件中進(jìn)行指定,我們采用

重量級(jí)的ORM還是輕量級(jí)的ORM,這樣我們也理想的實(shí)現(xiàn)了低耦合的特性。

       同時(shí),對(duì)于不同的文件的操作,我們可以支持多文件類(lèi)型的寫(xiě)入,當(dāng)然對(duì)于不同的數(shù)據(jù)庫(kù)存儲(chǔ),如果我們利用關(guān)系型數(shù)據(jù)庫(kù)我們需要ORM,對(duì)于對(duì)象數(shù)據(jù)庫(kù)的操作,或者

XML文件的操作,我們這時(shí)候的ORM就變了。

       4.2、提供緩存服務(wù)

         我們知道,我們第一篇中主要是通過(guò)自定義特性+反射的形式來(lái)處理:我們并沒(méi)有提供完整的特性操作,其實(shí)還有很多的情況,比如說(shuō),我們還可以提供對(duì)視圖的映射,提

供一個(gè)視圖的特性等。還有其他的特性有很多,后續(xù)會(huì)給出完整的代碼結(jié)構(gòu),我們知道自定義特性+反射,如果每次在將對(duì)象映射成數(shù)據(jù)庫(kù)表的時(shí)候,那么效率上是多么的低下

啊,那么這個(gè)時(shí)候,我們可以考慮使用緩存的方式,將數(shù)據(jù)庫(kù)表中的數(shù)據(jù)庫(kù)列與對(duì)象中的屬性列進(jìn)行映射,我們可以把這些對(duì)應(yīng)關(guān)系放在緩存中,那么如果我們?cè)诤罄m(xù)的處理中遇

到與數(shù)據(jù)庫(kù)相關(guān)操作,需要進(jìn)行對(duì)象映射的時(shí)候,我們都先會(huì)去緩存中查找有沒(méi)有指定鍵值的映射數(shù)據(jù)庫(kù)表列存在,存在取出生成SQL語(yǔ)句,否則通過(guò)反射取出對(duì)應(yīng)的數(shù)據(jù)庫(kù)表

列,放在緩存中。下面給出示意圖。將這個(gè)過(guò)程進(jìn)行描述:

image

當(dāng)然我這里給出的肯定是反向的根據(jù)對(duì)象生成操作數(shù)據(jù)的SQL語(yǔ)句的方式。這里沒(méi)有考慮,當(dāng)數(shù)

據(jù)庫(kù)表發(fā)生變化的時(shí)候,我應(yīng)該自動(dòng)同步緩存中的映射集合信息,當(dāng)然我們可以通過(guò)一定的策略,來(lái)實(shí)現(xiàn)這樣的雙向同步問(wèn)題。例如如下的方式可能就是可行的方案。

image

通過(guò)上述的方式,我們通過(guò)同步組件,在每次進(jìn)行數(shù)據(jù)操作之前,我們可以應(yīng)用更好的策略,比如記錄或者遍歷文件的修改狀態(tài),對(duì)比文件的最后修改日期,是不是發(fā)生修改,或者當(dāng)某個(gè)文件發(fā)生修

改之后,我們記錄在某個(gè)配置文件中,這樣我們可以提高同步的效率,因?yàn)橥ㄟ^(guò)這樣的方式,我們不需要每次檢查對(duì)象是不是發(fā)生變化了,這樣我們?nèi)绻l(fā)現(xiàn)對(duì)象沒(méi)有發(fā)生變化,

那么我們就不要讓同步組件去檢測(cè)對(duì)象是否發(fā)生變化,這樣就能提高效率,同時(shí)支持當(dāng)映射對(duì)象發(fā)生變化的時(shí)候,我們不用修改我們的關(guān)系數(shù)據(jù)庫(kù)。大家都知道,面向?qū)ο笤O(shè)計(jì)建

模與關(guān)系數(shù)據(jù)庫(kù)的最大難題就是雙方的變化的同步性的方案是很難定的,我這里只是給出一個(gè)簡(jiǎn)單的思路和方式,可能還有更好的方案,也請(qǐng)大家多多告訴我。

      4.3、Update語(yǔ)句的操作

       我不知道,你們?cè)诿嬖嚨臅r(shí)候,如果你經(jīng)常開(kāi)發(fā)底層的面向?qū)ο蟮腛RM的時(shí)候,應(yīng)該會(huì)遇到這樣的問(wèn)題,我們?cè)诓樵円粋€(gè)映射對(duì)象的時(shí)候,我們可能只需要取出這個(gè)對(duì)象的

部分列,而不是全部的數(shù)據(jù)列,這個(gè)時(shí)候,我們?nèi)绾沃付兀烤褪翘畛鋵?duì)象的時(shí)候,我們只需要填充指定的列?或者我們需要在在保存編輯的時(shí)候,我們不更新未發(fā)生變化的數(shù)據(jù)

庫(kù),其實(shí)主要是要求,我們?cè)谏蒘QL語(yǔ)句的時(shí)候,我們希望我們的更新語(yǔ)句中不要出現(xiàn),沒(méi)有發(fā)生變化的數(shù)據(jù)列的設(shè)置,這個(gè)如何做到呢?我想我們可以通過(guò)如下的2種方式來(lái)

做。

        1、通過(guò)對(duì)象的序列化,來(lái)復(fù)制一個(gè)對(duì)象,并且系統(tǒng)中緩存這個(gè)對(duì)象,在編輯之前,緩存,等到提交后,釋放這個(gè)對(duì)象。這個(gè)由系統(tǒng)默認(rèn)的提供方法。前提是標(biāo)記對(duì)象是編

輯狀態(tài),這樣在修改對(duì)象之前進(jìn)行復(fù)制,不然如果修改完了,再?gòu)?fù)制就沒(méi)有什么意義了

        2、通過(guò)字典來(lái)保存更新數(shù)值的數(shù)據(jù)列,通過(guò)數(shù)據(jù)字典來(lái)存放。我們?cè)谧值渲写娣庞成涞臄?shù)據(jù)列,將發(fā)生變化的數(shù)據(jù)列和數(shù)據(jù)列的值進(jìn)行標(biāo)記發(fā)生改變,我們?cè)谏筛抡Z(yǔ)

句的時(shí)候。直接遍歷這個(gè)集合,將列狀態(tài)發(fā)生改變的列生成相應(yīng)的操作語(yǔ)句即可。這些都是可行的方式,我們?cè)谇懊娴募軜?gòu)設(shè)計(jì)中也提到過(guò)的。都是給過(guò)思路的,這里我也不多復(fù)

述了。

        3、…。可能還有其他的更好的方式,還請(qǐng)大家多提出好的思路,我備注在這個(gè)位置!

       4.4、提供基礎(chǔ)的查詢方法。

        這里說(shuō)的提供基礎(chǔ)的查詢方法,指的是基于數(shù)據(jù)庫(kù)操作之上,我們提供幾個(gè)常用的查詢方法,包括自動(dòng)生成版本號(hào)的方法等,我們的版本號(hào)可以通過(guò)日期+流水號(hào)的形式來(lái)

生成,或者是其他的情況。GUID也是可行的辦法。不過(guò)維護(hù)起來(lái)可能不是很方便。所以底層提供相應(yīng)的操作方法更容易來(lái)做。

        我們這里考慮提供如下的基礎(chǔ)查詢方法,復(fù)雜的查詢方法,我們可以提供一個(gè)入口來(lái)做。例如我們提供如下幾類(lèi)方法:

        1、底層生成版本號(hào)的方法,自增ID流水號(hào),根據(jù)不同的生成規(guī)則自定義設(shè)置ID生成規(guī)則,來(lái)組織生成ID的通用方法。

        2、提供實(shí)體與數(shù)據(jù)庫(kù)行集之間的轉(zhuǎn)換,我們需要將數(shù)據(jù)庫(kù)記錄轉(zhuǎn)換為實(shí)體集合。通過(guò)查詢方法返回對(duì)象集合。這里提供返回指定主鍵的對(duì)象集合。

        3、返回一個(gè)數(shù)據(jù)表或者視圖中的所有記錄。

        4、返回傳入分頁(yè)個(gè)數(shù),和分頁(yè)排序字段,分頁(yè)條件的分頁(yè)集合。

        5、返回指定列的查詢方法。(這里沒(méi)有想到好的辦法,怎么樣的形式比較靈活能夠動(dòng)態(tài)的指定返回的列,比如說(shuō)1列,10列,5列等),希望大家提出好的意見(jiàn)和建議!

        6、提供統(tǒng)一的入口,編寫(xiě)SQL語(yǔ)句傳入到數(shù)據(jù)訪問(wèn)層中進(jìn)行查詢和檢索,根據(jù)指定的返回類(lèi)型來(lái)返回泛型對(duì)象。

        4.5、并發(fā)和事務(wù)控制

         我想一個(gè)系統(tǒng)中必須考慮的就是事務(wù)處理了,我們進(jìn)行批量操作的時(shí)候,如果數(shù)據(jù)不同步,那就太痛苦了,也是不能使用的系統(tǒng)的,我們希望我們的ORM能夠自動(dòng)的集成

事務(wù)和并發(fā),當(dāng)然這里說(shuō)的并發(fā)是當(dāng)用戶數(shù)上升到一定量的時(shí)候,就會(huì)產(chǎn)生這樣的問(wèn)題,理論上來(lái)說(shuō)只要有2個(gè)以上的用戶,就必須考慮并發(fā)操作!并發(fā)我們有幾個(gè)控制的思路,

總體來(lái)說(shuō)應(yīng)該說(shuō)說(shuō)我們前面的設(shè)計(jì)的內(nèi)部的一個(gè)自動(dòng)生成的版本號(hào),是最好的選擇。具體怎么個(gè)意思呢?我們來(lái)解釋下:

         對(duì)于并發(fā)控制,我們知道,并發(fā)控制的問(wèn)題:寫(xiě)丟失,讀出來(lái)的數(shù)據(jù)是臟數(shù)據(jù),無(wú)疑就是這么2個(gè)比較常見(jiàn)的問(wèn)題,那么我們?nèi)绾蝸?lái)對(duì)寫(xiě)丟失進(jìn)行限制呢?目前通用的方案

都是通過(guò)樂(lè)觀鎖來(lái)處理,二個(gè)人可以同時(shí)對(duì)某個(gè)信息進(jìn)行讀取,但是只能有一個(gè)人在進(jìn)行編輯,但是最后修改的內(nèi)容會(huì)把前面修改的信息覆蓋掉,這是樂(lè)觀鎖的處理方式。

        悲觀鎖,則是只要有人在修改,那么可能你不能進(jìn)行修改,也不能讀取,這種方式,當(dāng)然可以保證信息的修改的同步性和一致性,但是用戶的易用性和友好性方面不夠人性

化,相比來(lái)說(shuō),有人修改,就不能被其他人修改,但是可以讀取的方式體驗(yàn)方面要差一些,不過(guò)各有使用的場(chǎng)景,一般來(lái)說(shuō),悲觀鎖是樂(lè)觀鎖的一個(gè)補(bǔ)充。

        我們這里既不是樂(lè)觀鎖,也不是悲觀鎖的形式,通過(guò)版本來(lái)對(duì)某個(gè)記錄的版本進(jìn)行記錄,一旦發(fā)生改變,那么記錄的版本就要發(fā)生變化,我們這里對(duì)這個(gè)行集的版本的更新

可以通過(guò)ORM提供的版本的生成規(guī)則來(lái)生成一個(gè)版本號(hào),或者是通過(guò)觸發(fā)器來(lái)實(shí)現(xiàn),當(dāng)然性能也是我們需要考慮的部分。

        對(duì)于事務(wù),我想一般的不是分布式操作的應(yīng)用,我們通過(guò)數(shù)據(jù)庫(kù)提供的本身的事務(wù)服務(wù)來(lái)完成,基本上就可以滿足日常的需求,也沒(méi)有什么特別難的地方,我想這里我也就

不詳細(xì)的說(shuō)了,我們來(lái)簡(jiǎn)單的說(shuō)下,分布式事務(wù)的一致性,對(duì)于這種分布式的事務(wù)操作,我們可以采用離線并發(fā)模式來(lái)處理。這個(gè)怎么理解呢?就是通過(guò)工作單元來(lái)實(shí)現(xiàn)。我們把

每一個(gè)操作看著一個(gè)工作單元,如果我們?cè)趫?zhí)行某個(gè)事務(wù)操作的過(guò)程中,如果返回是0或者是其他的不是我們期望的結(jié)果時(shí),我們不會(huì)進(jìn)行任何的提交操作,如果全部執(zhí)行通過(guò),

我們循環(huán)所有的工作單元進(jìn)行提交,否則我們回滾所有的系統(tǒng)事務(wù)。我們把這樣的分布式事務(wù),看作一個(gè)業(yè)務(wù)事務(wù),由一些列的工作單元組成,這些工作單元看作是系統(tǒng)事務(wù)。

五、ORM相關(guān)代碼實(shí)現(xiàn)

         5.1、CUD的基本實(shí)現(xiàn)代碼:

           1,Create語(yǔ)句的實(shí)現(xiàn):

        private Dictionary<string, Column> _autoIncrementColumns = new Dictionary<string, Column>();
        private Dictionary<string, Column> _updateColumns = new Dictionary<string, Column>();

        public string TableName
        {
            get
            {
                return string.Empty;
            }
        }

        public Dictionary<string, Column> UpdateColumns
        {
            get
            {
                return this._updateColumns;
            }
            set
            {
                this._updateColumns = value;
            }
        }

        public Dictionary<string, Column> AutoIncrementColumns
        {
            get
            {
                return this._autoIncrementColumns;
            }
            set
            {
                this._autoIncrementColumns = value;
            }
        }

        public virtual IDbCommand GetDbCommand()
        {
            // 如果column的值沒(méi)有被更新過(guò),則返回null
            if (this.UpdateColumns.Count == 0)
            {
                return null;
            }

            ArrayList fieldList = new ArrayList();
            ArrayList valueList = new ArrayList();
            SqlCommand cmd = new SqlCommand();

            foreach (Column column in this.UpdateColumns.Values)
            {
                fieldList.Add("[" + column.Key + "]");
                valueList.Add("@" + column.Value);
            }

            string fieldString = string.Join(" , ", (string[])fieldList.ToArray(typeof(string)));
            string valueString = string.Join(" , ", (string[])valueList.ToArray(typeof(string)));
            string cmdText = string.Format("INSERT INTO [{0}]({1}) VALUES({2})",
                this.TableName,
                fieldString,
                valueString);

            string sqlGetIndentityID = null;

            if (this.AutoIncrementColumns.Count == 1)
            {
                sqlGetIndentityID = string.Format("SELECT [{0}] = SCOPE_IDENTITY()");
            }

            if (sqlGetIndentityID != null)
            {
                cmdText = cmdText + " ; " + sqlGetIndentityID;
            }

            cmd.CommandText = cmdText;

            return cmd;

        }
    }

下面給出Update語(yǔ)句,是從上面的更新集合中編輯,將列的狀態(tài)發(fā)生改變的列添加生成到語(yǔ)句中-示例代碼如下:

        public virtual IDbCommand GetDbCommand()
        {
            // 如果column的值沒(méi)有被更新過(guò),則返回null
            if (this.UpdateColumns.Count == 0)
            {
                return null;
            }

            ArrayList fieldList = new ArrayList();
            ArrayList valueList = new ArrayList();
            SqlCommand cmd = new SqlCommand();

            string updateSQL=string.Empty;
            foreach (Column column in this.UpdateColumns.Values)
            {
                if (column.State)
                    updateSQL += "[" + column.Key + "]=" + "@" + column.Value;
            }

           string cmdText=  string.Format("UPDATE {0} SET {1}={2}", updateSQL);

            cmd.CommandText = cmdText;

            return cmd;
        }

至于刪除的代碼比較簡(jiǎn)單,我這里就不給出刪除的代碼了,總體來(lái)說(shuō)形式是相同的。

             5.2、緩存服務(wù)代碼

        我有2篇關(guān)于緩存的介紹,緩存中最難搞的問(wèn)題就是緩存的過(guò)期的問(wèn)題,對(duì)應(yīng)反射的性能問(wèn)題也是存在過(guò)期的問(wèn)題,比如說(shuō)我們的數(shù)據(jù)庫(kù)表發(fā)生變化,或者對(duì)象中的屬性發(fā)

生變化后,那么我們的緩存中的內(nèi)容也需要進(jìn)行更新,不然我們生成的數(shù)據(jù)庫(kù)操作語(yǔ)句將會(huì)不正確。我們這里的策略就是將映射出來(lái)的對(duì)象,放在服務(wù)器中的緩存中,當(dāng)然對(duì)于

B/S和C/S系統(tǒng)中可能采取的緩存方式和策略還是有區(qū)別的。B/S我們的緩存可以采用緩存到服務(wù)器中,或者是通過(guò)緩存服務(wù)器來(lái)完成,一般是通過(guò)Remoting來(lái)將服務(wù)器與緩存

服務(wù)器完成通信。我們看看簡(jiǎn)單的示例代碼吧:

   public class Cache
   {
       private static System.Web.Caching.Cache cache = HttpRuntime.Cache;//這里是默認(rèn)取當(dāng)前應(yīng)用程序的服務(wù)緩存。

       public static object Get(string key)
       {
           return cache[key];
       }

       public static bool Remove(string key)
       {
           return !(null == cache.Remove(key));
       }

       public static void Set(string key, object value)
       {
           cache.Insert(key, value, null, System.Web.Caching.Cache.NoAbsoluteExpiration, TimeSpan.FromMinutes(3));
       }
   }

上面給出的緩存類(lèi)的示例代碼,具體的操作,使用反射后,將反射后對(duì)象元數(shù)據(jù)信息緩存起來(lái),通過(guò)對(duì)象名來(lái)緩存:

具體代碼如下:

           PropertyInfo[] property = null;
            if (Cache.Get("") != null)
            {
                property = (PropertyInfo[])Cache.Get("");
            }
            else
            {
                Type t = Type.GetType("");

                property = t.GetProperties();
            }

通過(guò)上面的幾行簡(jiǎn)單的代碼就能表達(dá)出我們上面講述的思路,具體如何過(guò)期,這個(gè)上面也給出了一些思路,可能大伙有更好的思路,我這里就不班門(mén)弄斧了。

      5.3,提供基礎(chǔ)的查詢服務(wù)

        我想大伙對(duì)于查詢語(yǔ)句的操作,應(yīng)該說(shuō)是司空見(jiàn)慣了吧,我們?nèi)绾文芨玫耐瓿山y(tǒng)一的查詢服務(wù)可能是我們關(guān)心的問(wèn)題,我這里不會(huì)給出多數(shù)據(jù)庫(kù)的實(shí)現(xiàn),但是可以給大伙

一個(gè)思路,我們這里定義返回的查詢命令的時(shí)候,如果說(shuō)支持多數(shù)據(jù)的話,可以定義一個(gè)統(tǒng)一的接口,不同的數(shù)據(jù)庫(kù)提供不同的實(shí)現(xiàn)接口,然后根據(jù)統(tǒng)一的ORM配置來(lái)調(diào)用不同的

組件來(lái)生成SQL語(yǔ)句,完成調(diào)用操作。

        相關(guān)的查詢服務(wù)代碼如下:

       /// <summary>
       /// 系統(tǒng)自動(dòng)生成的版本號(hào)
       /// </summary>
       /// <returns></returns>
       public string GetVersion()
       {
           return DateTime.Now.Year.ToString() + DateTime.Now.Month.ToString() + DateTime.Now.Day.ToString() + DateTime.Now.Minute.ToString() + DateTime.Now.Second.ToString();
       }

       public int GetMax<T>()
       {
           //根據(jù)T的類(lèi)型獲取T的最大列,完成查詢操作。
           string sqlText = " Select MAX(ISNULL(列名,0))+1 FROM TableName";

           return 0;
       }

       public List<T> GetAll<T>()
       {
           //根據(jù)T的類(lèi)型獲取T的最大列,完成查詢操作。
           string sqlText = " Select *  FROM TableName";

           return new List<T>();
       }

       public List<T> GetList<T>(string condition,int pagesize,string orderField)
       {
           //根據(jù)T的類(lèi)型獲取T的最大列,完成查詢操作。
           string sqlText = " Select *  FROM TableName where " + condition + " order by " + orderField;

           return new List<T>();
       }

      上面給出的不是全部的代碼,部分代碼還是大家自己去完成吧,我這里想的是,一些客戶比較復(fù)雜的自定義代碼通過(guò)一個(gè)接口傳入的形式,來(lái)完成基礎(chǔ)查詢服務(wù)的調(diào)用。

      我們這里給出通用的接口定義:

       CommandType CommandType
        {
            get;
            set;
        }

        string whereCondition
        {
            get;
            set;
        }

        string orderCondition
        {
            get;
            set;
        }

        string TableName
        {
            get;
            set;
        }

        Column[] ColumnList
        {
            get;
            set;
        }

        string SQL
        {
            get;
            set;
        }

                給出默認(rèn)幾類(lèi)示例的實(shí)現(xiàn):

    public class BaseSQL : ISelect
    {
        public System.Data.CommandType CommandType
        {
            get
            {
                throw new NotImplementedException();
            }
            set
            {
                throw new NotImplementedException();
            }
        }

        public string whereCondition
        {
            get
            {
                throw new NotImplementedException();
            }
            set
            {
                throw new NotImplementedException();
            }
        }

        public string orderCondition
        {
            get
            {
                throw new NotImplementedException();
            }
            set
            {
                throw new NotImplementedException();
            }
        }

        public string TableName
        {
            get
            {
                throw new NotImplementedException();
            }
            set
            {
                throw new NotImplementedException();
            }
        }

        public Column[] ColumnList
        {
            get
            {
                throw new NotImplementedException();
            }
            set
            {
                throw new NotImplementedException();
            }
        }

        public string SQL
        {
            get
            {
                throw new NotImplementedException();
            }
            set
            {
                throw new NotImplementedException();
            }
        }

        具體調(diào)用的代碼如下:

   public class SpecialSQL : BaseSQL
    {
        public void Test()
        {
            this.TableName = "";
            this.SQL = " SELECT * FROM TEST ";
            this.whereCondition = " ID=4 ";
            this.orderCondition = " ORDER BY ID DESC ";
        }
    }

      當(dāng)然這里的繼承的方式不是很推薦,可以采用抽象工廠的模式,來(lái)創(chuàng)建這個(gè)查詢對(duì)象,然后我們?cè)谡{(diào)用這個(gè)查詢對(duì)象的地方,我們可以自定義這個(gè)SQL查詢對(duì)象,后臺(tái)的

ORM自動(dòng)解析,完成自定義SQL語(yǔ)句的統(tǒng)一查詢服務(wù)入口。

      當(dāng)然如果您有更好的方案,可以提出來(lái),非常感謝!

六、本章總結(jié)

        本文主要是講述ORM中的數(shù)據(jù)訪問(wèn)層,我這里由于一些特殊的原因,代碼給出的不是特別的詳細(xì),一方面是由于之前的那部分的代碼丟了,現(xiàn)在一時(shí)難以還原,所以造成有

些代碼給出的不是特別完整的情況,請(qǐng)大家見(jiàn)諒,文章中的有些部分的內(nèi)容,我在實(shí)現(xiàn)的過(guò)程中也是遇到了不少的問(wèn)題,我現(xiàn)在的具體問(wèn)題列出來(lái),也請(qǐng)大家?guī)臀医鉀Q一下,我的

疑問(wèn),我目前在架構(gòu)設(shè)計(jì)的過(guò)程中遇到如下的問(wèn)題:

               1、我在實(shí)現(xiàn)服務(wù)層持久化透明服務(wù)的時(shí)候,我也想把查詢服務(wù)透明,意思就是業(yè)務(wù)對(duì)象與服務(wù)層只通過(guò)DTO來(lái)完成,業(yè)務(wù)對(duì)象的所有數(shù)據(jù)都通過(guò)服務(wù)層的訪問(wèn)來(lái)完成。

               2、如果現(xiàn)在有比較復(fù)雜的業(yè)務(wù)邏輯的操作語(yǔ)句的時(shí)候,我的這個(gè)SQL語(yǔ)句放在數(shù)據(jù)訪問(wèn)層好呢?還是放在哪里?應(yīng)該具體的職責(zé)劃分要明確。

               3、我只是希望業(yè)務(wù)邏輯層處理業(yè)務(wù)數(shù)據(jù),具體的業(yè)務(wù)數(shù)據(jù)怎么來(lái)的,我想讓業(yè)務(wù)邏輯只關(guān)心DTO。

               4、對(duì)于這樣的服務(wù)層提供的統(tǒng)一查詢方式的話,我在表現(xiàn)層調(diào)用的時(shí)候,如何傳參,能夠很好的組織參數(shù)的傳遞和調(diào)用,傳統(tǒng)的方式不再目前的考慮當(dāng)中。

           

it知識(shí)庫(kù)Step by Step-構(gòu)建自己的ORM系列-數(shù)據(jù)訪問(wèn)層,轉(zhuǎn)載需保留來(lái)源!

鄭重聲明:本文版權(quán)歸原作者所有,轉(zhuǎn)載文章僅為傳播更多信息之目的,如作者信息標(biāo)記有誤,請(qǐng)第一時(shí)間聯(lián)系我們修改或刪除,多謝。

主站蜘蛛池模板: 激情小说激情图片 | 视频久久| 久久国产乱子伦精品免费看 | 免费观看成人鲁鲁鲁鲁鲁视频 | 国产一区二区在线视频 | 色综合久久综合 | 美女扒开内衣看个够网站 | 情se五月天 | 四虎精品国产一区二区三区 | 日本久久精品免视看国产成人 | 久久国产精品国语对白 | 午夜久久免费视频 | 国产精品19禁在线观看2021 | 影音先锋国产资源 | 亚洲国产精品一区二区三区久久 | 国产91精品一区二区视色 | 天天狠天天透天天伊人 | 亚洲精品tv久久久久 | 日韩一区二区免费看 | 亚洲精品乱码蜜桃久久久 | 中文字幕免费在线视频 | 免费在线小视频 | 91短视频版在线观看www | 精新精新国产自在现拍 | 精品一区二区三区高清免费观看 | 亚洲欧美视频在线播放 | 夜夜爽天天狠狠九月婷婷 | 国产午夜视频高清 | 中文成人在线视频 | 亚洲天堂黄色 | 国产一区曰韩二区欧美三区 | 亚洲激情在线播放 | 欧美成人免费sss | 国产精品黄大片在线播放 | 国产伦乱 | 国产综合视频在线观看 | 国产在线精品福利大全 | 亚洲综合图色 | 黄色网在线看 | 日本精品一区二区三区视频 | 视频网站黄色 |