亚洲免费av电影一区二区三区,日韩爱爱视频,51精品视频一区二区三区,91视频爱爱,日韩欧美在线播放视频,中文字幕少妇AV,亚洲电影中文字幕,久久久久亚洲av成人网址,久久综合视频网站,国产在线不卡免费播放

        ?

        一種基于接口編程的高效通用數據訪問層的設計與實現

        2021-06-23 08:39:36徐照興
        河北水利電力學院學報 2021年2期
        關鍵詞:基類子類實例

        徐照興

        (江西服裝學院 大數據學院,江西南昌向塘經濟開發(fā)區(qū)麗湖中大道103號 330201)

        決定一個系統(tǒng)優(yōu)劣最關鍵的是系統(tǒng)的架構,系統(tǒng)架構的優(yōu)劣決定著系統(tǒng)具有的延遲與吞吐量、可用性與一致性、可擴展性、穩(wěn)定性等[1]。系統(tǒng)經典架構主要有基于接口編程的三層架構,該架構可以很好地從整體上對系統(tǒng)解耦。經典三層通常分為數據訪問層、業(yè)務邏輯層、表現層,大型系統(tǒng)通常會在經典三層架構的基礎上對業(yè)務邏輯層進行再封裝,使之形成新的一層,通常稱為服務層,這樣系統(tǒng)的架構就變成了四層,也就成為分布式系統(tǒng)架構[2]。不論幾層架構,數據訪問層是必須的,其功能主要是負責對數據庫的訪問。文中經過對多套開源框架分析,結合實戰(zhàn)開發(fā)經驗,給出一種基于接口編程思想,用Entity Framework技術實現數據訪問層的方案,并給出核心代碼,整個實現思路如圖1所示。

        圖1 數據訪問層實現思路總圖Fig.1 General diagram of data access layer implementation idea

        1 數據訪問層常用技術

        在.Net開發(fā)平臺下,數據訪問層實現技術主要有ADO.Net,NHibernate,Entity Framework(以下簡稱“EF”)。ADO.Net是一種最基本的數據庫訪問技術,訪問性能高,需要比較熟練掌握SQL Server數據庫技術。EF是典型的一種實現了ORM(Object Relational Mapping,對象關系映射)框架的技術,它底層是對ADO.Net技術進行了封裝,通過實體、關系型數據庫表之間的映射,使開發(fā)人員可以通過操作表實體而間接地操作數據庫,大大地提高了開發(fā)效率。EF與原生ADO.NET技術相比缺點是訪問性能稍差,主要是因為在編譯運行時有一個生成sql腳本的過程[3]。NHibernate也是一種實現了ORM框架的技術,它使用數據庫和配置信息來為應用程序提供持久化服務,也即在使用時要進行更多的配置[4],總體來說與Entity Framework技術差不多,但是NHibernate與Visual Studio開發(fā)環(huán)境的集成不如EF,所以本文選擇主要利用EF技術來實現數據訪問層。

        2 數據實體假設

        系統(tǒng)采用Model First方式設計數據庫,即先設計Model,然后根據Model生成數據庫。為了方便后面給出實現代碼及說明,假設系統(tǒng)有UserInfo(用戶)和OrderInfo(訂單)兩個實體,UserInfo實體擁有UName(用戶名)、Pwd(密碼)、ShowName(真實姓名)等屬性,OrderInfo實體擁有Content(訂單內容)、UserInfoId(訂單所屬的用戶Id)等屬性,它們之間的關系為1對多,實體數據模型如圖2所示。

        圖2 數據實體模型Fig.2 Data entity model

        3 關鍵技術分析與實現

        3.1 用EF技術實現高效查詢

        數據訪問層最基本職責就是封裝對實體的增刪改查方法,假設要對實體UserInfo進行封裝,即創(chuàng)建UserInfoDal類,此類中用EF對實體進行增加、修改、刪除方法都非常簡單。下面重點分析闡述如何根據用戶輸入的任意條件高效查詢數據。在ADO.Net數據庫訪問技術時往往會采用where拼接條件,這樣寫起來很繁瑣,性能比較差,也不利于擴展。采用EF來實現,要考慮參數類型和返回值類型2個問題。

        (1)方法參數類型

        要能接受用戶輸入的任意條件是一個條件,它要么為真要么為假,其返回值是bool類型,因此用委托Func作為參數類型。

        (2)方法返回值類型

        返回值是用戶,但返回的用戶個數是不確定的,因此不能用UserInfo,可以用List。但是應用List類型,數據就會立即加載到內存,而DAL層是不需要具體數據的,一般是在UI層、BLL層才真正需要數據。在需要數據的時候才加載數據到內存,這樣有利于提高系統(tǒng)的性能[5]。因此修改返回值類型為IQueryable,IQueryable類型為延遲加載。

        該方法參數Func是委托類型,返回值為IEnumerable類型,IEnumerable也為本地集合,只要轉為IEnumerable類型,立即就會加載數據到內存。也可以這樣理解,方法參數為Func委托類型時,執(zhí)行操作是查詢表中的全部數據加載到內存中,然后再根據條件進行篩選,如果數據量大,內存容易“爆掉”,因此需要對這個委托類型參數進行改進,具體改進如下:

        用Expression>類型,由于采用了封裝,操作結果發(fā)生了質的變化。Expression>返回值類型為IQeryable,而IQeryable為延遲加載,即數據不會立即加載到內存。

        利用EF技術實現根據用戶輸入任意條件高效查詢數據的代碼如下:

        Public IQueryableGetUsers(Expression>whereLambda)

        {

        Return

        db.UserInfo.Where(whereLambda).AsQueryable();

        }

        3.2 EF+Lambda高效分頁查詢

        Lambda分頁查詢需要的參數有pageSize(每頁多少條記錄)、pageIndex(查找的頁碼索引)、查詢條件、排序條件、升序(asc)還是降序(desc),此外,一般還會輸出查找到的記錄數total。最關鍵的就是查詢條件參數及排序條件參數如何表示。

        查詢條件與3.1節(jié)中的是一樣的,重點分析排序條件。

        排序條件是由用戶傳入,因此跟查詢條件參數類似。但Func的返回值類型不是固定的bool,如果根據Id排序就是int,如果根據用戶名排序就是string等,具體實現如下:

        把分頁查詢方法寫成泛型形式,也即泛型方法,這樣在調用方法時由用戶傳入,也即排序條件參數為:Expression>rderByLambda。這里S就表示由用戶根據排序字段的數據類型傳入的一種數據類型。

        分頁查詢返回值類型同樣為延遲加載類型,因此返回值類型設置為IQueryable

        3.3 封裝數據訪問層的基類關鍵技術

        為了提高代碼的復用性及系統(tǒng)的可擴展性,需要封裝數據訪問層的基類,取名為BaseDal,其功能就是封裝所有Dal層類公共的增刪改查方法。然后Dal層各實體類(比如UserInfoDal,OrderInfoDal等)只要繼承基類BaseDal就擁有了增刪改查方法。那么在基類下面所有方法就不能指明具體的類型,那如何處理呢?

        子類UserInfoDal繼承基類BaseDal時,可以通過子類傳入類型給基類,因此,基類就要能接收子類傳入的類型,也即基類要采用泛型類,同時約定傳入的類型要為引用類型和具有無參構造方法。

        3.4 通過接口隔離BLL層對DAL的依賴

        通常采用new實例化對象,會導致BLL層與DAL層緊密耦合在一起,即DAL層發(fā)生變化BLL層就必須跟著變。而項目設計原則為模塊內高內聚、模塊間低耦合[6]。即當DAL層發(fā)生變化,BLL層不需要變化或者變化達到最小。

        可以通過接口隔離BLL層對DAL的依賴,即讓BLL層依賴接口,不要依賴于DAL層,因為DAL層是具體的實現(即不依賴于具體實現),而依賴于接口,接口是抽象的(里面的方法等都只有一個定義而已),可以用不同的方法來實現接口,因此,需要建立接口層。然而有多少個實體,就需要建立多少個實體對應的接口,且每個接口里都是定義類似的抽象的增刪改查方法,因此,可以抽象出基類接口IBaseDal,同BaseDal一樣,它也需要設置為泛型,以便接收子類傳入的類型。

        有了上面的基類接口后,具體的子類接口(如IUserInfoDal)只需要去繼承基類接口IBaseDal,并傳入對應的實體類型即可。

        為了讓實例化對象返回值類型為接口類型,還需要讓對應數據訪問層子類(如UserInfoDal)去實現對應的接口。具體數據訪問層子類(UserInfoDal)的代碼結構升級改為如下形式:

        Public class UserInfoDal:BaseDal,IUserInfoDal

        {

        }

        然后,實例化具體數據訪問層子類就可以用接口類型去接收(即返回值類型為接口)。

        3.5通過抽象工廠實現BLL層與DAL層徹底解耦

        通過接口隔離BLL對DAL的依賴,代碼得到較大優(yōu)化,但是還有不足之處。

        因為業(yè)務邏輯層有很多BLL類,比如UserInfoBll,OrderInfoBll等,有多少個實體類就需要有多少個BLL類,而且UserInfoDal會用得非常頻繁,因為很多業(yè)務BLL都需要與用戶發(fā)生數據交互,如UserInfoDal()名稱發(fā)生改變(比如數據訪問驅動層實現技術發(fā)生改變,名稱由UserInfoDal改為了NhUserInfoDal),那么所有用到UserInfoDal的BLL類都要做相應的更改,這樣就非常麻煩,那么有沒有辦法改一個配置就可以呢?

        這就可以用抽象工廠,其本質是使用反射方式來實現[7]。要使用反射就要獲得當前程序集。數據訪問驅動層的不同實現方法其實就是程序集名稱不同,不過前提是不同數據訪問驅動層封裝同一個實體的DAL名稱要相同,這實際也就是約定大于配置思想。在項目中新建一個靜態(tài)的StaticDalFactory類,在該類下面創(chuàng)建GetUserInfoDal方法,返回值類型設置為接口類型IUserInfoDal。

        由于變化點只有一個程序集名稱,因此,可以把程序集的名稱放到配置文件(web.config)中去。

        對于靜態(tài)工廠層(StaticDalFactory),首先添加對配置文件的引用,即添加對System.Configuratuion程序集的引用。

        那么以后實現數據訪問驅動層的技術發(fā)生改變,只要修改配置文件web.Config中的節(jié)中key對應的value值即可。

        3.6 保證線程內共享一個上下文實例

        前面數據訪問層BaseDal中上下文實例[8]是通過new產生的,只要執(zhí)行到new所在代碼就會產生一個上下文實例??梢杂靡粋€單獨類來產生上下文實例,再新建一個DbContentFactory類,功能用來保證線程內共享一個上下文實例。

        在此類下創(chuàng)建一個方法GetCurrentDbContent(),通過該方法用來創(chuàng)建上下文對象,返回值類型設置為DbContext,因為Model層中如果還有其他的上下文對象,那么只要把new后面的具體上下文對象名稱更改就可以切換上下文對象。

        3.7 封裝數據訪問層統(tǒng)一入口DbSession類

        在數據訪問層繼續(xù)封裝一個DbSession類,讓它擁有所有DAL的實例和更新到數據庫的方法,也即是讓DbSession類為整個數據訪問層與數據庫的會話類,像EF上下文封裝了所有表對應實體集合DbSet[9],DbSession封裝所有DAL的實例。

        接下來把數據訪問層基類BaseDal.cs中所有Db.SaveChanges()代碼全部刪除,也即是不要在數據訪問層每一個操作都去與數據庫交互。這樣做優(yōu)點是數據提交的權利從數據庫訪問層提到了業(yè)務邏輯層。如果在數據庫訪問層每個方法都有SaveChanges()方法,那么每操作一次都會與數據庫發(fā)生交互。而到了業(yè)務層來了就非常靈活,多個操作可以“積攢”一起提交,當然需要的話也可以一個操作結束了就提交,只要加上DbSession.SaveChanges()語句即可。

        3.8 建立IDbSession接口,讓業(yè)務層依賴接口

        業(yè)務邏輯層中語句:DbSession dbsession=new DbSession();即DbSession所在層與BLL層之間緊密依賴,因此需定義一個IDbSession類,用來隔離DbSession所在層與BLL層之間的依賴,然后讓DbSession去實現IDbSession。

        但是這里還有問題,就是通過new實例化對象,只要執(zhí)行,就會產生新的實例。因此需要封裝成一次請求共用一個實例(比如封裝為GetCurrentDbSession方法)。然后回到業(yè)務邏輯層改造獲取dbsession實例代碼,采用上面封裝好的方法,這樣系統(tǒng)就又進一步得到了優(yōu)化。后續(xù)要得到userInfoDal等各個實例的DAL,可以通過統(tǒng)一的數據庫訪問入口DbSession來獲取。

        至此,數據訪問層從可擴展性、可復用性及可維護性等方面均得到了非常大的優(yōu)化。

        4 結束語

        系統(tǒng)具有可擴展性、可復用性及可維護性是一個基本要求,文中基于接口編程的思想,選擇.Net平臺,采用EF技術,一步步分析闡述了如何對數據訪問層進行優(yōu)化,并給出核心代碼,從而加深加速軟件技術開發(fā)人員更好地理解數據訪問層常用的技術思想,為同行提供一種數據訪問層的實現技術參考。數據訪問層實現技術不是一成不變的,沒有最好,只有更好,比如數據訪問層實例對象可以通過依賴注入方式(Spring.Net)注入到業(yè)務邏輯層,讀者可以在理解的基礎上根據系統(tǒng)的實際業(yè)務需求作出選擇或進一步優(yōu)化。

        猜你喜歡
        基類子類實例
        基于C#面向對象程序設計的封裝、繼承和多態(tài)分析
        卷入Hohlov算子的某解析雙單葉函數子類的系數估計
        關于對稱共軛點的倒星象函數某些子類的系數估計
        空戰(zhàn)游戲設計實例
        一種基于用戶興趣的STC改進算法
        服裝學報(2015年1期)2015-10-21 01:20:30
        虛機制在《面向對象程序設計C++》中的教學方法研究
        完形填空Ⅱ
        完形填空Ⅰ
        塊H矩陣新的子類
        關于Java繼承性的探討
        亚洲精品中文字幕导航| 无码不卡免费一级毛片视频 | 亚洲 欧美 国产 制服 动漫 | 亚洲熟女少妇精品综合| 久久天堂综合亚洲伊人hd妓女| 厨房玩丰满人妻hd完整版视频| 久久精品国产72国产精福利| 亚洲综合一区二区三区久久| 精品香蕉99久久久久网站| 免费无码黄动漫在线观看| 2021精品国产综合久久| 国产在线观看免费不卡视频| 久久亚洲道色综合久久| 色老板精品视频在线观看| 国产精品高潮无码毛片| 日本大片在线一区二区三区| 亚洲av熟女少妇久久| 亚洲精品一区久久久久久| 少妇无码av无码去区钱| 国产精品又污又爽又色的网站| 国产成人a级毛片| 少妇人妻200篇白洁| 亚洲欧美日韩国产综合专区| 精品老熟女一区二区三区在线| 久爱www人成免费网站| 比比资源先锋影音网| 国产精品美女一级在线观看| 一本之道日本熟妇人妻| 无遮挡呻吟娇喘视频免费播放| 久久久国产精品ⅤA麻豆| 中文字幕成人精品久久不卡| 日本精品视频二区三区| 日本公与熄乱理在线播放| 亚洲AV无码精品一区二区三区l| 国产少妇露脸精品自拍网站| 午夜免费电影| 五月天精品视频在线观看| 亚洲中文字幕无线乱码va| 亚洲色图视频在线免费看| 亚洲日韩av无码中文字幕美国 | 免费人成黄页网站在线观看国内|