1. 程式人生 > >EF多租戶例項:快速實現分庫分表

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