在.net core中完美解決多租戶分庫分表的問題
前幾天有人想做一個多租戶的平台,每個租戶一個庫,可以進行水準擴充,應用端根據登入資訊,切換到不同的租戶庫
計劃用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繼承了接口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