1. 程式人生 > >不吹不黑,跨平臺框架AspNetCore開發實踐雜談

不吹不黑,跨平臺框架AspNetCore開發實踐雜談

## 前言 ![](https://upload-images.jianshu.io/upload_images/8869373-e1529b0c4e91d0e7.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 最近邊學邊做,初步上手了AspNetCore的開發,對MVC這套熟悉了一下,因為之前沒有拿來做過獨立專案,都是和別人合作開發,所以前後端分離,我都只做WebApi,而且還是很小的專案(課設級別),生產環境用最多的應該是Python的Django框架,這次我把一個之前做的Django專案用AspNetCore重寫一遍,效能提升了不少,C#的效能真不是蓋的,AspNetCore這個框架的效能也很不錯,榜上有名的(WebApi),雖然MVC排不上名,但是效能依舊甩Django很多,Django每次上線前就做各種效能優化,恐怖,不過效能太好也不行,等會公司覺得工作量不飽和(逃) ok,既然是雜談,那也不用把條理梳理得很清楚,我隨意列幾個方面對比其他框架(Django和Spring之類)聊一聊~ 由於我是初學者,對各種概念的理解可能有偏差的地方請各位大佬指正,也歡迎大家一起交流哈哈 ## 依賴注入 ![](https://upload-images.jianshu.io/upload_images/8869373-eaf38529e04ecdfc.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 對於寫習慣Django的我來說,依賴注入以前是很少用到的,剛剛搜了一下,發現Stack Overflow上有一個討論(Why is IoC / DI not common in Python?)說得不錯,給我掃盲了一下,傳送門:https://stackoverflow.com/questions/2461702/why-is-ioc-di-not-common-in-python Python的模組是天生單例模式的,比起Java這種甚至單例模式有多少種實現方式都能進面試題的語言,不知道高到哪裡去了,C#好很多,有靜態類,不過在開發中還是會以Singleton模式註冊到IoC容器中來實現單例~ 依賴注入有個很形象的類比,就是把靜態語言當成動態指令碼語言來用:啟動時把一堆東西丟進去IoC容器裡,等到要用的時候告訴容器要給你什麼,容器就幫你生成,而在容器裡面的這堆東西又可以匯入別的依賴,這樣層層下來相互依賴,如果框架執行過程出問題的話排查起來很痛苦hhh,還要注意避免因為設計問題導致迴圈依賴等各類問題,所以感覺Django在設計上還是好,生產力是真的高,其他Web框架用得少,除了AspNetCore和Django這些,就用了傳統的Spring、Beego和其他小眾語言的MVC框架(我甚至用過dart寫後臺,然並卵),有時間試試新興的的Vert.x、WebFlux這類,應該會比較好玩~ 就這個IoC和DI來說AspNetCore和Spring差不多,功能上差不多,使用方法也差不多,hhh,不過寫起來肯定是不如Python暢快的,不過為啥我還要用AspNetCore這種東西呢,因為靜態型別語言寫起來爽呀,Drf寫介面特別快,但是寫起來基本靠猜,哈哈哈,感覺這個形容很貼切。最近有個FastApi的看起來不錯,據說是100%的型別註解,可以把Python當成靜態型別語言來寫,但是這種框架太新了,沒有經過市場的驗證,很難在生產環境用上… ## ORM ![](https://upload-images.jianshu.io/upload_images/8869373-39acee66f2f8b164.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 資料庫操作是現在Web框架的核心(誤?),我也不知道,反正Web開發基本就是CRUD,整天和資料庫打交道是沒錯的,所以ORM很重要,設計合理好用的ORM可以減少很多工作量,Django為啥受歡迎一大原因就是它的ORM很強大很好用,這應該也是動態語言的優勢之一吧。 .NetCore平臺上的其他ORM我只用過EF Core和Chloe(官網:https://github.com/shuxinqin/Chloe),這個Chloe也是一個國產ORM,用起來蠻方便的,但是不支援資料庫遷移,沒辦法根據程式碼生成資料庫表,這點還是有點不爽的。EFCore是微軟官方的ORM,自然是好用,支援資料庫遷移,這個就很方便了,然後其他特點我也總結不出來,因為用得不深,沒啥特別的體會。 這次專案我選的ORM是國產的FreeSQL,原因是偶然間在部落格園看到作者王婆賣瓜的文章,覺得還不錯,然後就拿來用一用,確實挺好用的,可以很輕量一句話完成資料庫連線建立,也可以像EFCore那樣有各種豐富的功能,而且也支援DB First,這個就很舒服了,這次因為是把Django專案遷移到AspNetCore,所以我打算先用原來的資料庫試試看,然後FreeSQL一通DB First之後居然美滋滋的可以用,就更堅定了要繼續用下去的信心,哈哈(雖然後面遇到了很多坑,大多是關於多對多關係的,被DjangoORM慣壞了) FreeSQL官網文件:https://github.com/dotnetcore/FreeSql/wiki 體驗下來,FreeSQL對外來鍵(一對多、多對一)、多對多、一對一關係的處理方式還是可以的,通過「導航屬性」,跟EFCore應該差不多,但是定義Model的時候如果有外來鍵,還有多定義一個欄位存Id,這點感覺有點反人類了,EFCore不用,直接引用物件即可,遷移之後反映到表裡就是一個外來鍵Id,不過這個FreeSQL是軟外來鍵,引用歸引用,關係全都在程式碼裡面處理,不在資料庫裡面生成外來鍵,這個也有它的好處,甚至可以說是一個優勢了,有時候維護表的完整性約束有點麻煩hhh 參考文章:.NET ORM 導航屬性到底可以解決什麼問題?https://www.cnblogs.com/kellynic/p/13575053.html 然後再小小對比了一下Kotlin的Ktorm,這也是一個優秀的ORM,上次我也小小的試用了一下,挺不錯的,除了沒有遷移功能沒法自動建表,這個Ktorm用起來類似EFCore的體驗,同樣是外來鍵直接引用就行,不用像FreeSQL那樣留一個Id欄位來儲存,各有利弊吧…不展開了 *PS:之前的文章裡吐槽了Ktorm之後被作者大佬看到找上來手把手指導我寫程式碼了(逃),有些坑真不是框架的問題,還是自己太菜了啊…* ## 資料庫 ![](https://upload-images.jianshu.io/upload_images/8869373-8dba01755d701da8.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 資料庫我用SQLite,反正小專案我全都用這個,效能好,部署方便,雖然有寫入鎖,但就幾個人在用的系統,要啥自行車? - 記一次 SQLite 效能優化 https://www.isaced.com/post-272.html - 每天4億行SQLite訂單大資料測試 https://cloud.tencent.com/developer/article/1016993 ## ViewModel ViewModel在分層架構中很重要,其實除了ViewModel還有一個叫DTO(Data Transfer Object)的概念,ViewModel和DTO在MVC架構中同屬於Model層,DTO也可以叫做Input Model,因為一般作為外部傳入資料的物件(顧名思義嘛),然後通常總是在說的Model,其實也可以叫Entity,這些物件是直接對應到資料庫中的表,一般在View或者Api中不直接呈現Model,而是呈現ViewModel,因為可能我們會對要輸出的資料做一些處理啦,比如增加欄位刪除欄位這些,用Model肯定不行,資料表都是固定的。 同理,在傳入資料的時候,和資料表也不一定重合的,所以需要藉助DTO,其實和ViewModel沒什麼嚴格的界限,你要拿DTO去呈現也行,只是我覺得ViewModel看名字就是拿來呈現的,習慣哈哈。 其實傳統的MVC、MVVM模式都已經有點跟不上時代了,我覺得現在的Web應用就得按照DDD(Domain-Driven Design)模式來設計,不過DDD初學有點複雜,概念很多,我也不好亂解釋,引用一下知乎的一段回答: >DDD簡單說是: 一個專案裡面有多個Bounded Context, 譬如說一個是前臺面向使用者的,一個是後臺面向公司內部人員的。每個Bounded Context裡面會分為多個aggregate。每個aggregate裡面包含了一堆需要保證事務性一致的物體,也就是說從全域性來說,每個aggregate都是當作一個整體。常見的例子就是Order(訂單)和OrderLine(訂單裡面的商品)。Entity包括Aggregate root都有唯一標識。兩者的區別是aggregate root全局裡面有唯一標識,而aggregate 內部其他entity只是在aggregate內部有唯一標識(也許你資料庫裡面有主鍵,但是這邊是指概念上來說這個唯一標識對全域性來說意義不大,只有在aggregate內部意義才大)。另外的value object就是沒有標識的物體,他們的意義就在於它的值,你可以想象成比較兩個entity是不是同一個只需要判斷ID是否相等,而判斷value objects需要看裡面的每個屬性是否一樣。 >![](https://upload-images.jianshu.io/upload_images/8869373-d514ca7d26cd74c5.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) > >作者:鮑牙叔 連結:https://www.zhihu.com/question/25256772/answer/77940547 來源:知乎 著作權歸作者所有。商業轉載請聯絡作者獲得授權,非商業轉載請註明出處。 然後,這麼多物件在轉來轉去,又有很多欄位是差不多的,一個個重新賦值顯得很傻也根本沒必要,這個時候AutoMapper就要用起來了,具體用法不是本文的討論範圍(參考下方列出的官方文件),不過提一點,AutoMapper是可以配置的,有哪些欄位不要的可以排除,我在Profile中是這麼寫的: ```c# public class VideoProfile : Profile { private readonly List _unmapped = new List { "HostEnvironment", "Previews", "OverallRating" }; public VideoProfile() { CreateMap(); ShouldMapProperty = (property) => !_unmapped.Contains(property.Name); } } ``` 把不要的欄位放在一個List裡面,然後用lambda配置 ShouldMapProperty 就好啦。 參考 - AutoMapper https://docs.automapper.org/en/latest/Getting-started.html - RESTful+FreeSql+AutoMapper https://luoyunchong.github.io/vovo-docs/dotnetcore/examples/freesql-sample-blog-restful-use-automapper.html#adding-profiles - FreeSql、AutoMapper處理多對多查詢對映 https://blog.csdn.net/XinShun/article/details/104755959 ## 一些關於C#語言的 ![](https://upload-images.jianshu.io/upload_images/8869373-79ebb68a613ef300.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) C#語言我用很久了,但是卻幾乎沒有專門去學習過語法,這門語言,emmm,下限低,上限很高,上手很簡單,但複雜度比Java高很多,語法糖很多,所以圈子裡的人很多有種高人一等的優越感哈哈,但其實國內的生態是比較差啦,有就是一些培訓班啥的在吹,不過國外可以感覺到是比較熱門的一個技術,平時遇到啥問題,可能用中文關鍵詞搜不到,但是換成英文可以輕鬆搜尋到很多高質量的答案,只能說國內的技術環境被阿里之類的大廠帶偏了,大家都去搞Java了,很多其他好技術和好的語言無人問津,可惜啊…… 這次專案也沒用到啥高大上的東西,就是泛型、擴充套件方法、高階函式這類,用得飛起,貼一小段程式碼來看看哈哈~ ```c# public static IList ToViewModels( this ISelect data, IService service, int limit = 0 ) where TModel : class where TViewModel : class { var limitData = limit == 0 ? data : data.Limit(limit); return limitData .ToList() .Select(service.Get) .ToList(); } public static IEnumerable ToSampleViewModels( this ISelect data, IService service, int limit = 0 ) where TModel : class where TViewModel : class { return data.ToViewModels(service) .Shuffle() .Take(limit); } ``` 這個程式碼就是把FreeSQL查詢資料庫的結果一鍵轉換為ViewModel,轉換過程是通過Service,功能很簡單,但是做成擴充套件方法然後呼叫真的不要太爽,減少了n多程式碼重複,很舒服~ 然後C#的高階函式一開始我有點不習慣,因為之前寫習慣python、dart和js,都是map、reduce、filter這些,但是C#的LINQ中卻換了個名字,map對應select、filter對應where,這就很像SQL的風格了,我一開始都找不到…… 總之C#語言值得好好學一學,對提高工作效率和程式設計思維是有幫助的!多看書就完事了! ![](https://upload-images.jianshu.io/upload_images/8869373-9c07b1e44a9fb8ce.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) ### 參考資料 - [C#中IEnumerable、ICollection、IList、List之間的區別](https://www.cnblogs.com/sunliyuan/p/5816666.html) - C#高階函式介紹 https://www.jianshu.com/p/8a8f3743969b ## 幾個庫 另外還有看到好像蠻不錯的幾個庫,我還沒用,目前已經把AspNetCore應用到工作中了,以後應該有機會把這些庫用上hhh - Util應用框架:https://github.com/dotnetcore/Util/blob/master/readme.md - Masuit.Tools:https://github.com/ldqk/Masuit.Tools ## 歡迎交流 我整理了一系列的技術文章和資料,在公眾號「程式設計實驗室」後臺回覆 linux、flutter、c#、netcore、android、kotlin、java、python 等可獲取相關技術文章和資料,同時有任何問題都可以在公眾號後臺