1. 程式人生 > >企業專案實戰 .Net Core + Vue/Angular 分庫分表日誌系統 | 簡單的分庫分表設計

企業專案實戰 .Net Core + Vue/Angular 分庫分表日誌系統 | 簡單的分庫分表設計

#前言 專案涉及到了一些設計模式,如果你看的不是很明白,沒有關係堅持下來,寫完之後去思考去品,你就會有一種突撥開雲霧的感覺,所以請不要在半途感覺自己看不懂選擇放棄,如果我哪裡寫的詳細,或者需要修正請聯絡我,謝謝。 #建立專案 ##1.SDK安裝 我們開發用的vs版本是2019 .Net Core的版本是3.1 下載 SDK 地址 :https://dotnet.microsoft.com/download ![](https://git.imweb.io/hdong/ImageBed/raw/master/EasyLoggerImages/CoreSDKDown.png) ##2.新建專案 ![](https://git.imweb.io/hdong/ImageBed/raw/master/EasyLoggerImages/Create1.png) ![](https://images.cnblogs.com/cnblogs_com/HDONG/1827694/o_200813143420CreateApi.png) 這裡選擇Core 版本是3.1 專案型別是API Docker支援我們不勾選,我會在後續給大家單獨再開一個系列 我們專講,慢慢來。 ![](https://git.imweb.io/hdong/ImageBed/raw/master/EasyLoggerImages/xiangmujiegou.png) 這裡可以看到一個非常乾淨的專案就創建出來了,專案結構就是這樣,裡面的詳情可以去看老張的第二個章節,講的很明白,我就不在重複了 https://www.cnblogs.com/laozhang-is-phi/p/9495620.html 進階可以去看開源原始碼 https://github.com/aspnet/MetaPackages/tree/master/src/Microsoft.AspNetCore 然後我們直接F5 啟動專案看看 是不是新建的專案是不是沒有問題,專案一切正常,我們開始進入正軌。 #專案思考 ##1.分表 分表這個功能,就是把相同結構不同名稱的多張表資料讀取出來,這個部分其實很簡單,我們常見的ORM都支援切換表名進行查詢。 ##2.分庫 分庫如何實現呢。 先來看一下我們常用的ORM框架是如何連線資料庫的。 ![](https://git.imweb.io/hdong/ImageBed/raw/master/EasyLoggerImages/SqlSugarCLien.png) SqlSugar連線資料庫 ![](https://git.imweb.io/hdong/ImageBed/raw/master/EasyLoggerImages/FreeSqlClient.png) FreeSql連線資料庫 它們有一個共同點,NEW一個物件傳遞資料庫連線字串,設定好資料庫型別,各自的xxx配置,就會得到一個連線的Client,然後就可以進行CRUD了。 那New多個物件,每個物件都是不同的連線字串豈不是就可以操作多個數據庫了。 ![](https://git.imweb.io/hdong/ImageBed/raw/master/EasyLoggerImages/errsql.PNG) 大家寫程式碼可別直接在業務/資料訪問層這麼寫,整不好就讓你下班領盒飯了。 那麼這種情境下因該如何設計能讓程式碼更加規範、易擴充套件呢! ##3.思考 思路就是這樣,那麼如果讓你來設計,你會怎麼做呢,大家可以自己嘗試著先去根據自己想法設計看看,然後我們下一節,我來給講解我的設計方案。 #設計要求 為了提高難度設計難度我們來同時相容FreeSql、SqlSugar2款現在最熱門的ORM。 我們設計要做到: ####易擴充套件(就算再來一個我也能輕鬆支援) ####切換快(不改動業務程式碼前提下,2個ORM框架我想用誰就用誰,隨便切換) ####可共存(可以取2款ORM各自優點在一起開發使用) #實戰 ##1.制定規範 ####①、我們先新建一個類庫 EasyLogger.DbStorage(ps:該類庫用於制定規範,提供介面) ####②、新建 Interface 資料夾 ####③、新建泛型介面 IAnyStorage (儲存器) 該介面規範字典操作標準方法。 這裡使用的ConcurrentDictionary 是一個併發字典。 ![](https://git.imweb.io/hdong/ImageBed/raw/master/EasyLoggerImages/IAngStorage.PNG) ``` public interface IAnyStorage where T : class { ConcurrentDictionary DataMap { get; } T GetByName(string name, string defaultName); void AddOrUpdate(string name, T val); void Remove(string name); void Clear(); } ``` ##2.遵循規範 我們先做SqlSugar的版本 ###①、新建 EasyLogger.SqlSugarDbStorage類庫 ###②、新建 Interface 資料夾 ###③、新建 ISqlSugarProviderStorage (SqlSugar連線提供程式儲存器) 介面繼承IAnyStorage >繼承IAnyStorage因為他是泛型繼承它,我們需要傳遞一個引數,他是什麼呢?當然是我們的SqlSugar連線提供程式了。 我們安裝NuGet包安裝 sqlSugarCore ###⑤、新建ISqlSugarProvider (SqlSugar連線提供程式) 介面作為泛型引數傳入 ![](https://git.imweb.io/hdong/ImageBed/raw/master/EasyLoggerImages/13151911.png) ![](https://git.imweb.io/hdong/ImageBed/raw/master/EasyLoggerImages/3151931.png) ###⑥、新建Impl 資料夾 ###⑦、新建 DefaultSqlSugarProviderStorage類繼承 ISqlSugarProviderStorage 進行SqlSugar連線提供程式儲存器的具體實現 ![](https://git.imweb.io/hdong/ImageBed/raw/master/EasyLoggerImages/813152539.png) ``` public class DefaultSqlSugarProviderStorage : ISqlSugarProviderStorage { public ConcurrentDictionary DataMap { get; private set; } public DefaultSqlSugarProviderStorage(IServiceProvider serviceProvider) { DataMap = new ConcurrentDictionary(); var tmpDataMap = serviceProvider.GetServices() .ToDictionary(item => item.ProviderName); foreach (var item in tmpDataMap) { this.AddOrUpdate(item.Key, item.Value); } } public void AddOrUpdate(string name, ISqlSugarProvider val) { DataMap[name] = val; } public void Clear() { DataMap.Clear(); } public ISqlSugarProvider GetByName(string name, string defaultName) { ISqlSugarProvider result = null; if (name == null) { if (!DataMap.TryGetValue(defaultName, out result)) { throw new Exception("沒有找到 DefaultName Provider"); } return result; } else if (DataMap.TryGetValue(name, out result)) { return result; } throw new ArgumentException($"沒有找到 {name} Provider"); } public void Remove(string name) { if (string.IsNullOrWhiteSpace(name)) { return; } this.DataMap.TryRemove(name, out ISqlSugarProvider result); } } ``` 字典的操作我想都能看明白,基礎差的朋友可能會覺得不懂的就是下面這句,這是做什麼呢,其實就是我們把注入ISqlSugarProvider的實現都查詢 出來,放到我們的DateMap集合中(好處後面我會實踐給大家講到),到此我們SqlSugar連線提供程式儲存庫就完成了。 ``` var tmpDataMap = serviceProvider.GetServices() .ToDictionary(item => item.ProviderName); foreach (var item in tmpDataMap) { this.AddOrUpdate(item.Key, item.Value); } ``` 差點SqlSugar連線提供程式的實現給漏了。 我們在 Impl 資料夾 新建 SqlSugarProvider類,繼承ISqlSugarProvider介面。 ![](https://git.imweb.io/hdong/ImageBed/raw/master/EasyLoggerImages/13161107.png) ``` public class SqlSugarProvider : ISqlSugarProvider { public string ProviderName { get; set; } public SqlSugarClient Sugar { get; set; } public SqlSugarProvider() { this.Sugar = this.CreateSqlSugar(); this.ProviderName = "DefaultSqlSugar"; } private SqlSugarClient CreateSqlSugar() { // todo 臨時 var db = new SqlSugarClient( new ConnectionConfig() { ConnectionString = "server=.;uid=sa;pwd=@jhl85661501;database=SqlSugar4XTest", DbType = DbType.SqlServer,//設定資料庫型別 IsAutoCloseConnection = true,//自動釋放資料務,如果存在事務,在事務結束後釋放 InitKeyType = InitKeyType.Attribute //從實體特性中讀取主鍵自增列資訊 }); return db; } public void Dispose() { this.Sugar.Dispose(); } } ``` CreateSqlSugar 方法是我從SqlSugar官方複製過來的,大家注意把ConnectionString改成自己的資料庫連線。 我們現在來配置一下 Startup 先看看效果。 ![](https://git.imweb.io/hdong/ImageBed/raw/master/EasyLoggerImages/3162050.png) ``` app.Use(async (context, next) => { var sqlStorage = app.ApplicationServices.GetService(); var sugarClient = sqlStorage.GetByName(null, "DefaultSqlSugar").Sugar; Console.WriteLine("檢視sugarClient"); }); ``` 我們成功的從SqlSugar連線提供程式儲存中,拿到SqlSugarClient連線。 #補充 下面程式碼是我在技術群裡看到使用FreeSql的方式,這麼寫沒有問題簡單單例的實現,我推薦大家使用上文中依賴注入的方式來使用! ![](https://git.imweb.io/hdong/ImageBed/raw/master/EasyLoggerImages/o_20081405020500814125827.png) ![](https://git.imweb.io/hdong/ImageBed/raw/master/EasyLoggerImages/o_20081405021100814125834.png) #結尾 回顧一下本節的內容。 #####1.我們新建統一的泛型 IAnyStorage介面(連線提供程式儲存庫)來規範呼叫。 #####2.我們建立了 ISqlSugarProviderStorage (SqlSugar連線提供程式儲存庫) 通過繼承IAnyStorage來規範介面實現。 #####3.新建了 ISqlSugarProvider (SqlSugar連線提供程式). #####4.我們完善了介面的實現。 #####5.我們成功在 Startup 中新建一個簡單的中介軟體 成功從SqlSugar連線提供程式儲存中,拿到SqlSugarClient連線。 #思考問題 我們把資料庫連線字串寫在(SqlSugar連線提供程式)合理嗎,是不是依賴太深,這個時候我們就用到控制反轉來降低依賴性,那麼具體怎麼做呢!