來到這篇隨筆,咱們繼續演示如何實現EF多租戶。html
今天主要是演示多租戶下的變形,爲下圖所示mysql
此次咱們的示例項目進行了精簡,僅有一個API項目,直接包含全部代碼。git
其中Controller,StoreContext,Entity都徹底和以往的示例如出一轍,這裏就再也不過多介紹了。github
具備主要區別的是 CombinedConnectionGenerator 和 Startup sql
1. 首先要關注的是做爲入口的 Startup ,仍是一個套路,分別在 ConfigureService 註冊EF多租戶, 在 Configure 配置中間件。數據庫
ConfigureService 仍是一向的簡單。可是注意這裏使用的 AddMySqlPerTable 這個模式。app
在混合的模式中,須要已最小的單元做爲服務註冊。因爲此次是數據庫和數據表混合模式,因此須要用數據表來註冊。ui
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 便可。this
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 spa
關鍵點有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://www.cnblogs.com/woailibian/p/12632019.html