EF多租戶例項:快速實現分庫分表
前言
來到這篇隨筆,我們繼續演示如何實現EF多租戶。
今天主要是演示多租戶下的變形,為下圖所示
實施
專案結構
這次我們的示例專案進行了精簡,僅有一個API專案,直接包含所有程式碼。
其中Controller,StoreContext,Entity都完全和以往的示例一模一樣,這裡就不再過多介紹了。
具有主要區別的是 CombinedConnectionGenerator 和 Startup
程式碼解釋
1. 首先要關注的是作為入口的 Startup ,還是一個套路,分別在 ConfigureService 註冊EF多租戶, 在 Configure 配置中介軟體。
ConfigureService 還是一貫的簡單。但是注意這裡使用的 AddMySqlPerTable 這個模式。
在混合的模式中,需要已最小的單元作為服務註冊。由於這次是資料庫和資料表混合模式,所以需要用資料表來註冊。
1 public void ConfigureServices(IServiceCollection services) 2 { 3 services.AddScoped<IConnectionGenerator, CombindedConnectionGenerator>(); 4 services.AddMySqlPerTable<StoreDbContext>(settings => 5 { 6 settings.ConnectionPrefix = "mysql_"; 7 }); 8 services.AddControllers(); 9 }
Configure的使用更加簡單,只需要新增中介軟體 TenantInfoMiddleware 即可。
1 public void Configure(IApplicationBuilder app, IWebHostEnvironment env) 2 { 3 if (env.IsDevelopment()) 4 { 5 app.UseDeveloperExceptionPage(); 6 } 7 8 app.UseMiddleware<TenantInfoMiddleware>(); 9 10 app.UseRouting(); 11 12 app.UseEndpoints(endpoints => 13 { 14 endpoints.MapControllers(); 15 }); 16 }
2. 這次需要自己實現 ConnectionGenerator
關鍵點有2個,
第一個關鍵點,由於我們的類庫是同時支援多個DbContext的,所以需要有TenantKey去區分。由於有種特殊情況,需要一個 ConnectionGenerator 同時支援多個 DbContext ,所以這裡提供了 MatchTenantKey 方法作為補充的判斷依據。
可以看出來,我們這裡TenantKey 為空,所以一般都不會匹配中。示例中完全是依靠 MatchTenantKey 來做匹配的。
第二個關鍵點,GetConnection 作為最主要的邏輯方法,通過對TenantName 的數字部分進行取模,最終拼接處ConnectionString的鍵值
並且通過 Configuration 獲取連線字串
1 public class CombindedConnectionGenerator : IConnectionGenerator 2 { 3 private readonly IConfiguration configuration; 4 public string TenantKey => ""; 5 6 public CombindedConnectionGenerator(IConfiguration configuration) 7 { 8 this.configuration = configuration; 9 } 10 11 12 public string GetConnection(TenantOption option, TenantInfo tenantInfo) 13 { 14 var span = tenantInfo.Name.AsSpan(); 15 if (span.Length > 4 && int.TryParse(span[5].ToString(), out var number)) 16 { 17 return configuration.GetConnectionString($"{option.ConnectionPrefix}container{number % 2 + 1}"); 18 } 19 throw new NotSupportedException("tenant invalid"); 20 } 21 22 public bool MatchTenantKey(string tenantKey) 23 { 24 return true; 25 } 26 }
檢驗結果
檢驗結果我覺得已經沒有必要的,都是同樣的套路,主要的區別是,之前的只有一個數據庫,或者多個數據庫
這次的混合模式,主要是一個數據庫作為一個container,裡面可以同時包含多個product資料表。
Container1
Container2
總結
其實這個例子也是非常簡單的,目的是讓每個人都能快速應用複雜的分庫分表
下一篇文章將會通過多租戶實現讀寫分離。
關於這個文章的所有程式碼,已經同步到Github
https://github.com/woailibain/kiwiho.EFcore.MultiTenant/tree/master/example/mix_mode/kiwiho.EFcore.MultiTenant.MixMode
&n