啊,終於到寫三層架構的時候了,老實說,我都不知道自己這個算不算三層架構,姑且就當它是吧,具體屬於哪一個體系,希望有大佬指點一下(^o^)/
不曉得有人注意到沒有,我寫了三篇博客,然后就改了三次標題ヽ( ̄▽ ̄)ノ,
從最開始的Core建數據庫,到Core數據庫操作,再到現在的Core建站,也算是下決心寫個系列啊,,感覺要更好久的樣子,,
好吧,不要在意那些細節,文中可能會有一些我不知道的坑,畢竟自己也是一邊自學一邊寫,不過保證功能還是能用的,發現有坑記得說,,我改,,(〃'▽'〃)
// ===================emmm,我是分割線===================
強烈推薦閱讀:設計模式六大原則 講的相當淺顯易懂,,
首先上一個截圖,看看現在的項目結構,今天的主角是DataBase文件里面的那一堆項目啊,BLL,DAL和Interface,,Models是生成數據庫時使用的,所以今天用不上,,
按我的理解,先說說正常的三層架構吧,
UI:界面層,這個層最簡單,只是給BLL傳遞數據,然后,將BLL返回的數據進行一些處理,方便展示,
BLL:業務邏輯層,接收UI層給的數據,寫一些業務邏輯,第一步干啥,第二步干啥,什么什么的,然后把界面需要的數據返回出去,感覺更像是一個API
DAL:數據訪問層,BLL的業務邏輯處理時,總要涉及到數據庫的操作,這時候就要用到DAL層了,,
還有一個Model層,用來傳遞數據的,,不在三層范疇,,,
不知道大家是怎么使用三層的,給大家展示一下以前學校教我們怎么用的三層架構啊,,
分別對應三個類,UI層:HomeController,BLL層:DT_UserBLL,DAL層:DT_UserDAL
1 // UI層 2 public IActionResult Index(int userID) 3 { 4 5 // 根據條件,返回用戶 6 // 和BLL說,給你一堆條件,幫我把這些人找出來 7 var userList = DT_UserBLL.GetUser(0,18); 8 9 return View(userList); 10 11 }
1 /// <summary> 2 /// BLL層,返回符合條件的用戶 3 /// </summary> 4 /// <param name="sex">性別</param> 5 /// <param name="age">年齡</param> 6 /// <returns></returns> 7 public List<DT_User> GetUser(int sex, int age) 8 { 9 10 #region 數據校驗 11 12 // 性別檢測,0:女,1:男 13 if (sex != 0 && sex != 1) 14 // 拒絕人妖 15 return null; 16 17 // 年齡檢測,[0,150]歲 18 if (age < 0 || 150 < age) 19 // 拒絕妖怪 20 return null; 21 22 #endregion 23 24 // 和DAL說,數據我校驗好了,不是惡搞, 25 // 幫我查出來這些人,然后我交給UI就完事兒了,, 26 return DT_UserDAL.GetUser(int sex, int age).ToList(); 27 }
1 /// <summary> 2 /// DAL層,返回符合條件的用戶 3 /// </summary> 4 /// <param name="sex">性別</param> 5 /// <param name="age">年齡</param> 6 /// <returns></returns> 7 public IQueryable<DT_User> GetUser(int sex, int age) 8 { 9 DbContext DB = new DbContext(); 10 11 return DB.Set<DT_User>().Where(c=>c.Sex==sex&&c.Age==age); 12 }
當時學着感覺蠻好的,挺新奇的一個編程思想,不過每一個數據表對應的DAL里面都得寫一套增刪查改,,簡直是災難,,[○・`Д´・ ○]
出來實習之后,花了個把星期,把我們老大寫的一個框架看明白了,就按圖索驥地寫了起來,嘿嘿
其實和三層架構差不多的,只是把每個數據表對應的DAL里面的增刪查改全部提出來,封裝成了一個類,,
然后對這個類進行繼承,具體操作如下,,,
首先啊,要大概了解一下依賴注入,,講真,這個我也是一臉懵逼,所以就不復制百度百科了,,
說說自己的理解吧,,,,emmm,此處可能有大量謬論,建議不要被我誤導了,看看就好,別往心里去
依賴注入這東西就好像一個全局的字典類型變量,,都是以鍵值對的方式存儲的
因為注冊依賴注入服務的大部分語法是醬紫的,,,
1 services.AddTransient(typeof(IDT_UserService), typeof(DT_UserService));
而services這個變量的話,就像一個容器,用來存儲這些鍵值對的,具體從哪來的,我也不知道,ヽ( ̄д ̄;)ノ
而要使用的話,語法是醬紫的,,,
1 public class HomeController : Controller 2 { 3 private IDT_UserService _UserService; 4 5 public HomeController(IDT_UserService _UserService) 6 { 7 // 依賴注入得到實例 8 this._UserService = _UserService; 9 } 10 11 public IActionResult Index() 12 { 13 ViewBag.list = _UserService.LoadEntites(c => true); 14 15 return View(); 16 } 17 }
對的,完全不需要new,,其原理,,起碼我不曉得,感覺甚是神奇,,
先注冊一個依賴注入的服務,然后要實例的時候,直接在構造函數里面把鍵的類型寫上就好,,
好了,灌毒就到此為止了,,還是繼續上代碼吧,,
首先,得寫一個數據庫操作的底層類DalService又因為很多地方調用,所以,肯定是泛型,,
然后為了解耦和方便注入,所以實現一個接口IDalService,
我暫時只寫了添加和查詢的方法,,其他的方法可以自由發揮,,不過記得先寫接口,然后去實現接口中新加的方法,,不然無法使用的,,

1 public interface IDalService<T> where T : class, new() 2 { 3 T AddEntity(T entity); 4 5 IQueryable<T> LoadEntites(Expression<Func<T, bool>> where); 6 7 int SaveChanges(); 8 9 }

1 /// <summary> 2 /// 數據訪問層:DAL 3 /// </summary> 4 /// <typeparam name="T"></typeparam> 5 public class DalService<T> : IDalService<T> where T : class, new() 6 { 7 8 private DbContext DbWrite; 9 10 /// <summary> 11 /// 獲得數據庫上下文 12 /// </summary> 13 /// <param name="dbContext">數據庫上下文類,各自更改成自己的</param> 14 public DalService(DBCodeFirst dbContext) 15 { 16 DbWrite = dbContext; 17 } 18 19 public T AddEntity(T entity) 20 { 21 DbWrite.Set<T>().Add(entity); 22 return entity; 23 } 24 25 public IQueryable<T> LoadEntites(Expression<Func<T, bool>> where) 26 { 27 return DbWrite.Set<T>().Where(where); 28 } 29 30 public int SaveChanges() 31 { 32 return DbWrite.SaveChanges(); 33 } 34 35 }
然后就沒有DAL層啥事了,,咱們去看BLL層
同樣的寫一個業務邏輯的父級類BllService,依舊是泛型,以及實現接口IBllService

1 public interface IBllService<T>where T : class, new() 2 { 3 T AddEntity(T entity,bool IsSave); 4 5 IQueryable<T> LoadEntites(Expression<Func<T, bool>> where); 6 7 int SaveChanges(); 8 }

1 /// <summary> 2 /// 數據邏輯層:BLL 3 /// </summary> 4 public class BllService<T> : IBllService<T> where T : class, new() 5 { 6 7 /// <summary> 8 /// 數據庫服務 9 /// </summary> 10 protected IDalService<T> DBService; 11 12 public BllService(IDalService<T> dalService) 13 { 14 this.DBService = dalService; 15 } 16 17 /// <summary> 18 /// 保存實體 19 /// </summary> 20 /// <param name="entity"></param> 21 /// <param name="IsSave"></param> 22 /// <returns></returns> 23 public T AddEntity(T entity, bool IsSave) 24 { 25 entity = DBService.AddEntity(entity); 26 if (IsSave) 27 { 28 if (SaveChanges() > 0) 29 return null; 30 } 31 return entity; 32 } 33 34 /// <summary> 35 /// 查詢數據 36 /// </summary> 37 /// <param name="where"></param> 38 /// <returns></returns> 39 public IQueryable<T> LoadEntites(Expression<Func<T, bool>> where) 40 { 41 return DBService.LoadEntites(where); 42 } 43 44 /// <summary> 45 /// 保存數據庫 46 /// </summary> 47 /// <returns></returns> 48 public int SaveChanges() 49 { 50 return DBService.SaveChanges(); 51 } 52 }
然后基本就完成了,,我們可以在BLL層創建一個DT_User的邏輯處理類,繼承BllService,並實現接口IDT_UserService

1 public interface IDT_UserService : IBllService<DT_User> 2 { 3 DT_User Insert(); 4 5 List<DT_User> GetList(); 6 }

1 public class DT_UserService : BllService<DT_User>, IDT_UserService 2 { 3 /// <summary> 4 /// 用於實例化父級,DBService變量 5 /// </summary> 6 /// <param name="dal"></param> 7 public DT_UserService(IDalService<DT_User> dal) : base(dal) 8 { 9 10 } 11 12 public DT_User Insert() 13 { 14 DT_User user = new DT_User 15 { 16 Password = new Random().Next(0, 101) + "", 17 UserName = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") 18 }; 19 return AddEntity(user, true); 20 } 21 22 public List<DT_User> GetList() 23 { 24 return LoadEntites(c => true).ToList(); 25 } 26 27 }
最后使用的話,要把他們統統注冊到服務里面,新建一個類DIBllRegister,用來注冊這些和數據庫相關的服務

1 /// <summary> 2 /// Bll層依賴注入 3 /// </summary> 4 public class DIBllRegister 5 { 6 7 public void DIRegister(IServiceCollection services) 8 { 9 // 用於實例化DalService對象,獲取上下文對象 10 services.AddTransient(typeof(IDalService<>), typeof(DalService<>)); 11 12 // 配置一個依賴注入映射關系 13 services.AddTransient(typeof(IDT_UserService), typeof(DT_UserService)); 14 } 15 }
在Startup的ConfigureServices方法中添加兩行代碼
1 /// <summary> 2 /// 運行時調用此方法。使用此方法向容器添加服務。 3 /// </summary> 4 /// <param name="services"></param> 5 public void ConfigureServices(IServiceCollection services) 6 { 7 services.AddOptions(); 8 9 // 數據庫連接字符串 10 var conStr = Config.GetVal<string>(ConfigKey.ConStr); 11 services.AddDbContext<DBCodeFirst>(options => options.UseSqlServer(conStr)); 12 13 DIBllRegister bllRegister = new DIBllRegister(); 14 bllRegister.DIRegister(services); 15 16 services.AddMvc(); 17 }
然后我們就可以愉快的使用三層架構來寫項目了,,ヽ(≧∀≦)ノ
示例以及項目結構如下:
運行結果:
注意事項:
- BLL層的類一定要繼承BllService,並實現它對應的接口,參考上文DT_UserService類的格式
- BLL,DAL任何類要添加方法時,一定要在對應的接口中有個同樣的入口,不然無法調用
- BLL層添加類時,記得在DIBllRegister的DIRegister中添加一行注冊服務的代碼,不然無法調用
- 差不多就這些,我想起來了再加,,,
其實這個是我從Framework搬過來的,心塞得簡直不要不要的,,,填坑日記就不寫出來了,,
具體的搭建思想也不太好用文字表述,大佬不要吐槽,萌新可以照着步驟去建一個小項目調試着看,,
個人感覺還是比較好懂的,,畢竟,基本上全是核心代碼還帶注釋,加一個使用樣例,
然后就是下集預告了,雲服務器的FTP發布和數據庫連接吧,,畢竟雲服務器到手辣么久了,也該拉出來溜溜,,(❁´◡`❁)*✲゚*
最后,,有坑記得說,,,,