日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > c/c++ >内容正文

c/c++

第九节:基于MVC5+AutoFac+EF+Log4Net的基础结构搭建

發(fā)布時(shí)間:2023/12/10 c/c++ 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 第九节:基于MVC5+AutoFac+EF+Log4Net的基础结构搭建 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

一. 前言

  從本節(jié)開始,將陸續(xù)的介紹幾種框架搭建組合形式,分析每種搭建形式的優(yōu)勢(shì)和弊端,剖析搭建過程中涉及到的一些思想和技巧。

(一). 技術(shù)選型

  1. DotNet框架:4.6

  2. 數(shù)據(jù)庫(kù)訪問:EF 6.2 (CodeFrist模式)

  3. IOC框架:AutoFac 4.8.1 和 AutoFac.MVC5 4.0.2

  4. 日志框架:log4net 2.0.8

  5. 開發(fā)工具:VS2017

(二). 框架目標(biāo)

  1.?一個(gè)項(xiàng)目同時(shí)連接多個(gè)相同種類的數(shù)據(jù)庫(kù),在一個(gè)方法中可以同時(shí)對(duì)多個(gè)數(shù)據(jù)進(jìn)行操作。

  2.?支持多種數(shù)據(jù)庫(kù):SqlServer、MySQL、Oracle,靈活的切換數(shù)據(jù)庫(kù)。

  3.?抽象成支持多種數(shù)據(jù)庫(kù)連接方式:EF、ADO.Net、Dapper。

?

二. 搭建思路

?1. 層次劃分

  將框架分為:Ypf.Data、Ypf.IService、Ypf.Service、Ypf.DTO、Ypf.Utils、Ypf.AdminWeb 六個(gè)基本層(后續(xù)還會(huì)補(bǔ)充 Ypf.Api層),每層的作用分別為:

  ①.?Ypf.Data:存放連接數(shù)據(jù)庫(kù)的相關(guān)類,包括EF上下文類、映射的實(shí)體類、實(shí)體類的FluentApi模式的配置類。

  ②.?Ypf.IService:業(yè)務(wù)接口層,用來約束接口規(guī)范。

  ③.?Ypf.Service:業(yè)務(wù)層,用來編寫整套項(xiàng)目的業(yè)務(wù)方法,但需要符合Ypf.IService層的接口約束。

  ④.?Ypf.DTO: 存放項(xiàng)目中用到的自定義的實(shí)體類。

  ⑤.?Ypf.Utils: 工具類

  ⑥.?Ypf.AdminWeb: 表現(xiàn)層,系統(tǒng)的展示、接受用戶的交互,傳遞數(shù)據(jù),業(yè)務(wù)對(duì)接。

PS:后續(xù)會(huì)補(bǔ)充Ypf.Api層,用于接受移動(dòng)端、或其他客戶端接口數(shù)據(jù),進(jìn)行相應(yīng)的業(yè)務(wù)對(duì)接處理。

2. Ypf.Data層的剖析

  把EF封裝到Y(jié)pf.Data層,通過Nuget引入EF的程序集,利用FluentAPI的模式先進(jìn)行配置(實(shí)際項(xiàng)目多種模式配合使用),該層的結(jié)構(gòu)如下:

PS:EF的關(guān)閉默認(rèn)策略、EF的DataAnnotations、EF的FluentAPI模式, 在關(guān)閉數(shù)據(jù)庫(kù)策略的情況下,無論哪種模式都需要顯式的 ToTable來映射表名,否則會(huì)提示該類找不到。

EF配置詳情參考:

? ? ? ? ?第十五節(jié): EF的CodeFirst模式通過DataAnnotations修改默認(rèn)協(xié)定

? ? ? ? ?第十六節(jié): EF的CodeFirst模式通過Fluent API修改默認(rèn)協(xié)定

3.?Service層和IService層簡(jiǎn)單的封裝一下

【PS:這個(gè)地方是個(gè)關(guān)鍵點(diǎn),需要考慮多種不同的寫法,然后進(jìn)行封裝

  ①.【Ypf.Service】層只有一個(gè)BaseService泛型類封裝,【Ypf.IService】層并沒有設(shè)置IBaseService接口,設(shè)置了一個(gè)IServiceSupport標(biāo)識(shí)接口(沒有任何內(nèi)容),需要“AutoFac注入”的所有子類IxxxService都要實(shí)現(xiàn)IServiceSupport接口。

  ②.【Ypf.Service】層中有很多自定義的 xxxService,每個(gè)xxxService都要實(shí)現(xiàn)【Ypf.IService】層的IxxxService層接口,這里的xxxService層劃分并不依賴表名劃分,自定義根據(jù)業(yè)務(wù)合理起名即可。

  ③. xxxService類中,利用using() 包裹EF的上下文“db”便于釋放,然后把EF上下文傳入到泛型的BaseService<T>類的構(gòu)造函數(shù)中,可以調(diào)用其封裝的方法。

  ④.利用AutoFac實(shí)現(xiàn)在控制器中屬性的注入,相應(yīng)的配置均寫在Global文件中。

  ⑤.控制器中的Action僅僅負(fù)責(zé)傳值和簡(jiǎn)單的一些判斷,核心業(yè)務(wù)全部都寫在Service層中。

4. 利用AutoFac實(shí)現(xiàn)Ypf.AdminWeb層與Ypf.Service層解耦

  利用AutoFac進(jìn)行整合,使Ypf.AdminWeb層只需要引入YpfIService層即可,但需要改一下Ypf. Service輸出路徑使其程序集輸出到Y(jié)pf.AdminWeb層中。

?解析:利用AutoFac把Ypf.Service中的所有類注冊(cè)給它的全部實(shí)現(xiàn)接口(一個(gè)類可能實(shí)現(xiàn)了多個(gè)接口),并且把實(shí)現(xiàn)類中的屬性也進(jìn)行注冊(cè)(實(shí)現(xiàn)類中也可能包含屬性的注入)。

AutoFac的配置詳情參考:?

? ? ? ? ?第二節(jié):框架前期準(zhǔn)備篇之AutoFac常見用法總結(jié)

5. 將Log4net整合到Y(jié)pf.Utils層中

  解析:主要配置了兩種模式,輸出到“txt文本文檔”和“SQLServer數(shù)據(jù)庫(kù)中”。其中“文本文檔”又分了兩種模式,全部輸入到一個(gè)文檔中 和 不同類型的日志輸入到不同文檔下,在調(diào)用的時(shí)候通過傳入?yún)?shù)來區(qū)分存放在哪個(gè)文件夾下。

Log4net的配置詳情參考:

  第一節(jié):框架前期準(zhǔn)備篇之Log4Net日志詳解

6.?完善【Ypf.Service】層中BaseService的封裝

?  封裝EF常用的增刪改查的方法,這里暫時(shí)先不擴(kuò)展EF插件的方法,分享一下代碼。

?BaseService

?

三. 剖析核心

1. 如何實(shí)現(xiàn)同時(shí)操作多個(gè)相同類型的不同結(jié)構(gòu)的數(shù)據(jù)庫(kù)。

  首先【Ypf.Data】層中新建一個(gè)存放的實(shí)體的文件夾,如“EntityTest”,用來引入另外一個(gè)數(shù)據(jù)庫(kù)的存放實(shí)體和DbContext上下文,然后在【Ypf.Service】層中,雙Using,往BaseService類中傳入不同db上下文即可實(shí)現(xiàn)訪問不同的數(shù)據(jù)庫(kù),如果要對(duì)多個(gè)數(shù)據(jù)庫(kù)開啟事務(wù),手動(dòng)開啟msdtc服務(wù),然后使用Transactions包裹,進(jìn)行事務(wù)一體操作。

  詳細(xì)的使用步驟見:實(shí)戰(zhàn)測(cè)試。

2.?體會(huì)【Ypf.IService】層 和 引入IOC框架的作用

【PS:依賴倒置原則的核心就是:面向接口編程】

(1). 接口層的作用:

  a. 便于開發(fā)人員分工開發(fā),寫業(yè)務(wù)的單獨(dú)去寫業(yè)務(wù),對(duì)接的單獨(dú)去對(duì)接,而且事先把接口協(xié)議定好,那么對(duì)接的人員就不需要等業(yè)務(wù)人員全部寫完代碼,就可以對(duì)接了,無非最后再測(cè)試而已。

  b. 降低修改代碼造成的成本代價(jià),使以接口為基礎(chǔ)搭建起來的框架更加穩(wěn)健。

舉例1:?三層架構(gòu) 數(shù)據(jù)庫(kù)訪問層、業(yè)務(wù)邏輯層、UI調(diào)用層。?(非此套框架的模式,后面考慮這么改進(jìn))

①. 數(shù)據(jù)庫(kù)訪問層中有一個(gè) MySqlHelp類,提供鏈接MySQL數(shù)據(jù)增刪改查的方法。

②. 業(yè)務(wù)邏輯層有一個(gè)登錄業(yè)務(wù) CheckLogin(MySqlHelp mysql,string userName,string pwd)。

③. UI調(diào)用層要調(diào)用CheckLogin方法,這時(shí)候?qū)嵗粋€(gè)MySqlHelp對(duì)象,傳到CheckLogin方法中即可。

  有一個(gè)天,要求支持oracle數(shù)據(jù)庫(kù),所以數(shù)據(jù)庫(kù)訪問層中增加了一個(gè)oracleHelper類,UI調(diào)用層按照常規(guī)實(shí)例化了一個(gè)oracleHelper對(duì)象,傳到CheckLogin方法中,發(fā)現(xiàn)我的天!!!!CheckLogin竟然不支持oracleHelper對(duì)象,同時(shí)發(fā)現(xiàn)類似的所有業(yè)務(wù)層的方法都不支持oracleHelper類,這個(gè)時(shí)候悲劇就發(fā)生了,如果全部改業(yè)務(wù)層的方法,基本上完蛋。

所以根本的解決方案:依賴倒置原則,即面向接口編程。

①. 數(shù)據(jù)庫(kù)訪問層聲明一個(gè)接口IHelper,里面有增刪改查方法,MySqlHelp和oracleHelper都實(shí)現(xiàn)IHelper接口。

②. 業(yè)務(wù)邏輯層有一個(gè)登錄業(yè)務(wù)改為依賴接口IHelper, CheckLogin(IHelper iHelper,string userName,string pwd)。

③. UI調(diào)用層要調(diào)用CheckLogin方法,想連哪個(gè)數(shù)據(jù),就實(shí)例化哪個(gè) eg IHelper iHelper=new MySqlHelp(); 或者 IHelper iHelper=new oracleHelper(),此處考慮和IOC框架結(jié)合,連代碼都不用改,直接改配置文件就行了,就可以切換實(shí)例,然后調(diào)用CheckLogin即可。

舉例2:?類A,類B,類C。

類A中的方法需要傳入類B的實(shí)例,通常在類A中實(shí)例化一下類B,但如果想讓類A依賴類C,你會(huì)發(fā)現(xiàn)改動(dòng)非常大,類A中的方法原先是類B的參數(shù)全部需要改。

所以解決方案:類B和類C都實(shí)現(xiàn)接口I,類A中方法的參數(shù)由原先的類B改為接口I,這樣類A想依賴誰,只需要 I i=new B() 或者 I i=new C(),所有的方法都不用改,也可以再升級(jí)一下,這里不直接實(shí)例化,利用IOC框架或者手寫反射,只需要改一下配置文件,就能控制 到底是 new B 還是 new C 。

?(2). 引入IOC框架的作用:

  解決的問題1:現(xiàn)有的框架模式(Service層using引入EF上下文,傳入到BaseService類中),如何實(shí)現(xiàn)快速切換數(shù)據(jù)庫(kù)?

  a.首先在【Ypf.Data】層引入MySQL數(shù)據(jù)庫(kù)所需要的程序集,配置文件也改成連接MySQL的。(此處需要詳細(xì)測(cè)試)

  b. 新建一個(gè)【Ypf.Service2】層,同樣實(shí)現(xiàn)對(duì)應(yīng)業(yè)務(wù),只不過是連接不同類型的數(shù)據(jù)庫(kù)(比如它連接的是MySql數(shù)據(jù)庫(kù)),生成路徑也輸出到【Ypf.AdminWeb】層中,最后只需要改一下AutoFac讀取的配置文件“DllName”改為“Ypf.Services2”即可,就可以實(shí)現(xiàn)切換數(shù)據(jù)。

  總結(jié):該模式雖然能實(shí)現(xiàn)“相同業(yè)務(wù)、相同表”的不同類型的數(shù)據(jù)庫(kù)切換(比如SQLServer→MySQL),但是需要重新寫一個(gè)整層【Ypf.Service2】,雖然基本上是復(fù)制,但是有一定工作量的。但是另外通過手寫IOC也可以實(shí)現(xiàn)(反射+簡(jiǎn)單工廠+配置文件),看不到IOC框架的優(yōu)勢(shì)所在。

  IOC強(qiáng)大之處在于框架本身為我們封裝好了很多便于開發(fā)的方法,拿AutoFac來說吧,能靈活的控制創(chuàng)建對(duì)象的(每次請(qǐng)求都創(chuàng)建、單例、一個(gè)Http請(qǐng)求內(nèi)單例)

四. 實(shí)戰(zhàn)測(cè)試

這里準(zhǔn)備兩個(gè)數(shù)據(jù)庫(kù),分別是:YpfFrame_DB 和?YpfFrameTest_DB

①:YpfFrame_DB中,用到了表:T_SysUser 和?T_SysLoginLog,表結(jié)構(gòu)如下

②.?YpfFrameTest_DB 表中用到了T_SchoolInfor,表結(jié)構(gòu)如下

開始測(cè)試

1. 測(cè)試增刪改查,包括基本的事務(wù)一體。

在【Ypf.IService】層中新建ITestService接口,在【Ypf.Service】層中新建TestService類,實(shí)現(xiàn)ITestService接口, 定義TestBasicCRUD方法,進(jìn)行測(cè)試,代碼如下。

1 /// <summary>2 /// 1.測(cè)試基本的增刪改查,事務(wù)一體3 /// </summary>4 /// <returns></returns>5 public int TestBasicCRUD()6 {7 using (DbContext db = new MyDBContext1())8 {9 BaseService<T_SysUser> T_SysUserService = new BaseService<T_SysUser>(db); 10 BaseService<T_SysLoginLog> T_SysLoginLogService = new BaseService<T_SysLoginLog>(db); 11 //1.增加操作 12 T_SysUser t_SysUser = new T_SysUser() 13 { 14 id = Guid.NewGuid().ToString("N"), 15 userAccount = "123456", 16 userPwd = "XXX", 17 userRealName = "XXX", 18 appLoginNum = 1, 19 addTime = DateTime.Now 20 }; 21 T_SysUserService.AddNo(t_SysUser); 22 23 //2.修改操作 24 T_SysLoginLog t_SysLoginLog = T_SysLoginLogService.Entities.Where(u => u.id == "1").FirstOrDefault(); 25 if (t_SysLoginLog != null) 26 { 27 t_SysLoginLog.userId = "xxx"; 28 t_SysLoginLog.userName = "xxx"; 29 T_SysLoginLogService.ModifyNo(t_SysLoginLog); 30 } 31 //3.提交操作 32 return db.SaveChanges(); 33 } 34 }

2. 測(cè)試一個(gè)方法中查詢多個(gè)數(shù)據(jù)庫(kù)。

在ITestService接口中定義ConnectManyDB方法,并在TestService中實(shí)現(xiàn)該方法,代碼如下:

1 /// <summary>2 /// 2. 同時(shí)連接多個(gè)數(shù)據(jù)庫(kù)進(jìn)行3 /// </summary>4 /// <param name="userList"></param>5 /// <param name="schoolList"></param>6 public void ConnectManyDB(out List<T_SysUser> userList, out List<T_SchoolInfor> schoolList)7 {8 using (DbContext db = new MyDBContext1())9 using (DbContext db2 = new MyDBContext2()) 10 { 11 BaseService<T_SysUser> T_SysUserService = new BaseService<T_SysUser>(db); 12 BaseService<T_SchoolInfor> T_SchoolInforService = new BaseService<T_SchoolInfor>(db2); 13 14 //執(zhí)行數(shù)據(jù)庫(kù)查詢操作 15 userList = T_SysUserService.GetListBy(u => true); 16 schoolList = T_SchoolInforService.GetListBy(u => true); 17 } 18 }

  分析:想連接幾個(gè)數(shù)據(jù)庫(kù),就需要先在【Ypf.Data】層中新建對(duì)應(yīng)數(shù)據(jù)庫(kù)的實(shí)體、實(shí)體配置文件、EF上下文,然后在【Ypf.Service】層對(duì)應(yīng)的方法中實(shí)例化對(duì)應(yīng)的 EF上下文,然后傳入到BaseService類中即可。

3. 測(cè)試一個(gè)方法中事務(wù)一體處理多個(gè)數(shù)據(jù)庫(kù)的crud操作。

?在ITestService接口中定義ManyDBTransaction方法,并在TestService中實(shí)現(xiàn)該方法,代碼如下:

1 /// <summary>2 /// 3. 同時(shí)對(duì)多個(gè)數(shù)據(jù)庫(kù)進(jìn)行事務(wù)一體的CRUD操作3 /// 注:需要手動(dòng)開啟msdtc服務(wù)(net start msdtc)4 /// </summary>5 public void ManyDBTransaction()6 {7 using (TransactionScope trans = new TransactionScope())8 {9 try 10 { 11 DbContext db = new MyDBContext1(); 12 DbContext db2 = new MyDBContext2(); 13 14 BaseService<T_SysUser> T_SysUserService = new BaseService<T_SysUser>(db); 15 BaseService<T_SchoolInfor> T_SchoolInforService = new BaseService<T_SchoolInfor>(db2); 16 17 //執(zhí)行業(yè)務(wù)操作 18 T_SysUserService.DelBy(u => u.id == "1"); 19 T_SchoolInforService.DelBy(u => u.id == "1"); 20 21 //最終提交事務(wù) 22 trans.Complete(); 23 } 24 catch (Exception ex) 25 { 26 var msg = ex.Message; 27 //事務(wù)回滾 28 Transaction.Current.Rollback(); 29 throw; 30 } 31 } 32 }

  分析:同時(shí)連接多個(gè)數(shù)據(jù)庫(kù),并對(duì)多個(gè)數(shù)據(jù)庫(kù)進(jìn)行事務(wù)性的crud操作,這個(gè)時(shí)候必須用 【TransactionScope事務(wù)】,前提要手動(dòng) 【net start msdtc?】開啟對(duì)應(yīng)服務(wù),這樣整個(gè)事務(wù)通過“Complete”方法進(jìn)行提交,通過Transaction.Current.Rollback()方法進(jìn)行事務(wù)回滾,各自db的SaveChange不起作用,但還是需要SaveChange的。

4. 測(cè)試xxxSevice子類中也可以通過AutoFac進(jìn)行IxxxService的模式進(jìn)行屬性的注入。

?在【Ypf.IService】層中新建ITestService2接口,在【Ypf.Service】層中新建TestService2類,實(shí)現(xiàn)ITestService接口, 定義GetUserInfor方法,進(jìn)行測(cè)試,代碼如下。

?View Code

在TestService中定義ITestService2屬性,如下:

在TestService中定義如下方法,內(nèi)部用TestService2進(jìn)行調(diào)用,可以調(diào)用成功,從而證明xxxSevice子類中也可以通過AutoFac進(jìn)行IxxxService的模式進(jìn)行屬性的注入。

5. 測(cè)試Log4net的分文件夾和不分文件的使用。

?先分享配置文件:

?View Code

分享對(duì)應(yīng)的封裝類:

?View Code

代碼測(cè)試:

?

?

?

?

?

!

  • 作???????者 :?Yaopengfei(姚鵬飛)
  • 博客地址 :?http://www.cnblogs.com/yaopengfei/
  • 聲?????明1 : 本人才疏學(xué)淺,用郭德綱的話說“我是一個(gè)小學(xué)生”,如有錯(cuò)誤,歡迎討論,請(qǐng)勿謾罵^_^。
  • 聲?????明2 : 原創(chuàng)博客請(qǐng)?jiān)谵D(zhuǎn)載時(shí)保留原文鏈接或在文章開頭加上本人博客地址,否則保留追究法律責(zé)任的權(quán)利。

總結(jié)

以上是生活随笔為你收集整理的第九节:基于MVC5+AutoFac+EF+Log4Net的基础结构搭建的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。