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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM