前几天有人想做一个多租户的平台,每个租户一个库,可以进行水平扩展,应用端根据登录信息,切换到不同的租户库

计划用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

到此这篇关于详解在.net core中完美解决多租户分库分表的问题的文章就介绍到这了,更多相关.net core多租户分库分表内容请搜索www.887551.com以前的文章或继续浏览下面的相关文章希望大家以后多多支持www.887551.com!