在.net core中完美解決多租戶分庫分表的問題
阿新 • • 發佈:2020-04-14
前幾天有人想做一個多租戶的平臺,每個租戶一個庫,可以進行水平擴充套件,應用端根據登入資訊,切換到不同的租戶庫
計劃用ef core實現,他們說做不出來,需要動態建立dbContext,不好實現
然而這個使用CRL很輕鬆就能解決了
以下為演示資料庫,有兩個庫testdb和testdb2,查詢結果如下
目標:
根據傳入登入資訊連不不同的庫,查詢返回結果,如登入人為01,返回d1.default,登入人為02 返回 d2.default
實際上這個需求就是分庫分表的實現,通過設定資料庫/表對映關係,根據傳入的定位資料進行匹配,找到正確的庫表配置,生成資料訪問物件
以core控制檯程式為例
class Program { static IServiceProvider provider; static Program() { var services = new ServiceCollection(); services.AddCRL<DBLocationCreator>(); services.AddScoped<Code.Sharding.MemberManage>(); provider = services.BuildServiceProvider(); provider.UseCRL(); } static void Main(string[] args) { label1: var instance = provider.GetService<Code.Sharding.MemberManage>(); var data = new Code.Sharding.MemberSharding(); data.Code = "01"; instance.SetLocation(data); var find1 = instance.QueryItem(b => b.Id > 0)?.Name; Console.WriteLine($"定位資料輸入{data.Code},查詢值為{find1}"); data.Code = "02"; instance.SetLocation(data); var find2 = instance.QueryItem(b => b.Id > 0)?.Name; Console.WriteLine($"定位資料輸入{data.Code},查詢值為{find2}"); Console.ReadLine(); goto label1; } }
上面程式碼中,通過SetLocation方法傳入定位資料Code,通過QueryItem方法查詢出資料並打印出來
通過services.AddCRL<DBLocationCreator>()注入定位配置,DBLocationCreator繼承了介面IDBLocationCreator
這裡完全符合core注入規範,可以通過配置或資料庫儲存動態讀取定位設定
public class DBLocationCreator : IDBLocationCreator { ISettingConfigBuilder _settingConfigBuilder; public DBLocationCreator(ISettingConfigBuilder settingConfigBuilder) { _settingConfigBuilder = settingConfigBuilder; } public void Init() { //自定義定位 _settingConfigBuilder.RegisterLocation<Code.Sharding.MemberSharding>((t, a) => { var tableName = t.TableName; var dbName = a.Code == "02" ? "testdb2" : "testdb"; var dataBase = $"Data Source=.;Initial Catalog={dbName};User ID=sa;Password=123"; //返回定位庫和表名 return new CRL.Sharding.Location(dataBase, tableName); }); _settingConfigBuilder.RegisterDBAccessBuild(dbLocation => { var connectionString = "Data Source=.;Initial Catalog=testdb;User ID=sa;Password=123"; if (dbLocation.ShardingLocation != null) { connectionString = dbLocation.ShardingLocation.DataBaseSource; } return new CRL.DBAccessBuild(DBType.MSSQL, connectionString); }); } }
在Init方法裡,實現了兩個操作,通過RegisterLocation定義如何根據定位資料Code,返回不同的庫/表
通過RegisterDBAccessBuild實現資料訪問
執行測試程式,結果輸出為
上面程式碼通過自定義定位引數和定位規則,沒有任何耦合,呼叫也很簡單,完美達到了預期效果
測試程式碼地址:https://github.com/CRL2020/CRL.NetStandard/tree/master/Test/CRLCoreTest