本文3.0版本文章
本文涉及的內容,同樣適用於3.0版本,不用修改。
前言
書接上文:前幾回文章中,我們花了三天的時間簡單了解了下接口文檔Swagger框架,已經完全解放了我們的以前的Word說明文檔,並且可以在線進行調試,而且當項目開始之中,我們可以定義一些空的接口,或者可以返回假數據,這樣真正達到了前后端不等待的缺陷,還是很不錯的,當然,這離我說的前后端分離還是相差甚遠,今天呢,我們就簡單搭建下我們的項目架構。
本項目是我自己的一個真實項目,數據都是真實的,之前搭建過一個MVC + EF Code First的項目,本項目就是基於這個了,前一段時間我已經搭建起來了,是這樣的,本系列教程會重新開始。
零、完成圖中的粉色部分
先簡單解釋下各層之間的調用關系:
除了項目對外暴露的是 Api 展示層,和核心的實體 Model 層外,
倉儲模塊(作為一個數據庫管理員,直接操作數據庫,實體模型):
BaseRepository(基類倉儲) 繼承實現了 接口IBaseRepository,這里放公共的方法,
AdvertisementRepostitory 繼承 BaseRepository<Advertisement>, IAdvertisementRepository
Service模塊(處理業務邏輯,可以直接使用ViewModel視圖模型):
BaseService 調用 BaseRepository,同時繼承 IBaseService
AdvertisementServices 繼承 BaseServices<Advertisement>, IAdvertisementServices
2019-08-30:關於倉儲的相關話題
很多人都有一個這樣的想法,倉儲就是Dal層?我這里簡單說一下兩者的區別(我Blog.Core項目可能不是體現的出來,DDD可能更好理解):
1、倉儲是一種模式,可以單建一層,也可以放到基礎設施層,
而Dal是三層架構種的某一層,是一個架構
2、倉儲官方的定義,他是一個管理者,去管理實體對象和ORM映射對象的一個集合,是ORM操作db,
而Dal就是完完全全的操作db數據庫了,
請注意,不要把 Sqlsugar 當成三層中的 sqlhelper,不一樣!
3、倉儲更多的是一個聚合,在下一個系列DDD中,我們說到了一個概念,一個聚合的划分其實就是一個倉儲。
4、然后我們進一步細化,一個倉儲 = 一個聚合 = 有一個聚合根 = 一個微服務!
多個微服務之間交互,就是通過聚合根來的。
一、創建實體Model數據層
其中,Models文件夾中,存放的是整個項目的數據庫表實體類,這里是手動創建的,當然也可以自動創建,在以后的文章中我會提到,用到的是SqlSugar的T4創建,這里先埋一個伏筆。
提示:這個伏筆已經完成,地址《 三十二║ 四種方法快速實現項目的半自動化搭建》
然后,VeiwModels文件夾,是存放的DTO實體類,在開發中,一般接口需要接收數據,返回數據,我之前都是這么紅果果的使用的,后來發現弊端很大,不僅把重要信息暴露出去(比如手機號等),還對數據造成冗余(比如我需要接收用戶的生日,還需要具體的年、月、日這就是三個字段,當然您也可以手動拆開,這只是一個栗子,所以不能直接用數據庫實體類接收),就用到了DTO類的轉換,但是頻繁的轉換又會麻煩,別慌,以后的文章中,我們會引用AutoMapper來自動轉換,這里再買一個伏筆。
提示:這個伏筆已經完成,地址《十三 || DTOs 對象映射使用》
最后的是MessageModel和TableModel,大家也基本一看就能明白,因為在前端接口中,需要固定的格式,以及操作,不能把數據直接發出去,會報錯,在以后的Vue開發中,會提到這個,這里又買了一個伏筆。 如下:
/// <summary> /// 通用返回信息類 /// </summary> public class MessageModel<T> { /// <summary> /// 操作是否成功 /// </summary> public bool Success { get; set; } /// <summary> /// 返回信息 /// </summary> public string Msg { get; set; } /// <summary> /// 返回數據集合 /// </summary> public List<T> Data { get; set; } }
整個項目運行,沒錯,繼續創建下一層。
二、設計倉儲接口與其實現類
創建Blog.Core.IRepository和 Blog.Core.Repository 倉儲層:
這里簡單說下倉儲層:repository就是一個管理數據持久層的,它負責數據的CRUD(Create, Read, Update, Delete) service layer是業務邏輯層,它常常需要訪問repository層。有網友這么說:Repository(倉儲):協調領域和數據映射層,利用類似與集合的接口來訪問領域對象。Repository 是一個獨立的層,介於領域層與數據映射層(數據訪問層)之間。它的存在讓領域層感覺不到數據訪問層的存在,它提供一個類似集合的接口提供給領域層進行領域對象的訪問。Repository 是倉庫管理員,領域層需要什么東西只需告訴倉庫管理員,由倉庫管理員把東西拿給它,並不需要知道東西實際放在哪。
我們定義了IRepository層,提供了所有的操作接口,今天搭建框架,我簡單地寫一個實例,明天我們將把所有的方法嵌套進去。
在 IAdvertisementRepository.cs 中,添加一個求和接口
public interface IAdvertisementRepository { int Sum(int i, int j); }
然后再在 AdvertisementRepository.cs 中去實現該接口,記得要添加引用,這個應該都會,就不細說了。
public class AdvertisementRepository : IAdvertisementRepository { public int Sum(int i, int j) { return i + j; } }
運行項目,一起正常,繼續往下。
三、設計服務接口與其實現類
創建 Blog.Core.IServices 和 Blog.Core.Services 業務邏輯層,就是和我們平時使用的三層架構中的BLL層很相似:
Service層只負責將Repository倉儲層的數據進行調用,至於如何是與數據庫交互的,它不去管,這樣就可以達到一定程度上的解耦,假如以后數據庫要換,比如MySql,那Service層就完全不需要修改即可,至於真正意義的解耦,還是得靠依賴注入,這下一節我們會講到。
這里在 IAdvertisementServices 中添加接口
namespace Blog.Core.IServices { public interface IAdvertisementServices { int Sum(int i, int j); } }
然后再在 AdvertisementServices 中去實現該接口
public class AdvertisementServices : IAdvertisementServices { IAdvertisementRepository dal = new AdvertisementRepository();
public int Sum(int i, int j) { return dal.Sum(i, j); } }
注意!這里是引入了三個命名空間
using Blog.Core.IRepository;
using Blog.Core.IServices;using Blog.Core.Repository;
四、創建 Controller 接口調用
將系統默認的ValueController刪除,手動添加一個BlogController控制器,可以選擇一個空的,也可以選擇一個帶有默認讀寫實例的。如下:
[Produces("application/json")] [Route("api/Blog")] [Authorize(Policy ="Admin")] public class BlogController : Controller { // GET: api/Blog [HttpGet] public IEnumerable<string> Get() { return new string[] { "value1", "value2" }; } // GET: api/Blog/5 [HttpGet("{id}", Name = "Get")] public string Get(int id) { return "value"; } // POST: api/Blog [HttpPost] public void Post([FromBody]string value) { } // PUT: api/Blog/5 [HttpPut("{id}")] public void Put(int id, [FromBody]string value) { } // DELETE: api/ApiWithActions/5 [HttpDelete("{id}")] public void Delete(int id) { } }
接下來,在應用層添加服務層的引用
using Blog.Core.IServices;
using Blog.Core.Services;
然后,改寫Get方法
·······// GET: api/Blog /// <summary> /// Sum接口 /// </summary> /// <param name="i">參數i</param> /// <param name="j">參數j</param> /// <returns></returns> [HttpGet] public int Get(int i,int j) { IAdvertisementServices advertisementServices = new AdvertisementServices(); return advertisementServices.Sum(i,j); }
F5 運行項目,調試如下:
天呀!出錯辣!別慌,還記得昨天咱們加的權限么,嗯!就是那里,手動模擬登陸,獲取Token,注入,不會的可以看上一篇,然后再執行,結果:
五、結語
好啦,今天的工作暫時到這里了,你可以看到整體項目的搭建,結構,如何引用,如何測試等,當然,這里還是有很多小問題,比如:
·如果每個倉儲都需要這么寫,至少是四遍,會不會太麻煩;
·每次Controller接口調用,需要引入很多命名空間
·等等等等
這些問題,下一節我們都會帶大家一起去慢慢解決!
六、Github && Gitee
https://github.com/anjoy8/Blog.Core.git
https://gitee.com/laozhangIsPhi/Blog.Core