net core中多租戶分庫分表


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>()注入定位配置,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實現數據訪問

 對象定義

復制代碼
    public class MemberSharding : CRL.IModel
    {
        [CRL.Attribute.Field(KeepIdentity=true)]//保持插入主鍵
        public int Id
        {
            get;
            set;
        }
        public string Name
        {
            get;
            set;
        }
        public string Code;
    }
    public class MemberManage : CRL.Sharding.BaseProvider<MemberSharding>
    {

    }
復制代碼

 

運行測試程序,結果輸出為

 

上面代碼通過自定義定位參數和定位規則,沒有任何耦合,調用也很簡單,完美達到了預期效果

測試代碼地址:https://github.com/CRL2020/CRL.NetStandard/tree/master/Test/CRLCoreTest


免責聲明!

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



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