详解在.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实现数据访问

运行测试程序,结果输出为

上面代码通过自定义定位参数和定位规则,没有任何耦合,调用也很简单,完美达到了预期效果

测试代码地址:https://github.com/CRL2020/CRL.NetStandard/tree/master/Test/CRLCoreTest

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

(0)

相关推荐

  • MyBatis利用MyCat实现多租户的简单思路分享

    前言 本文的多租户是基于多数据库进行实现的,数据是通过不同数据库进行隔离.下面话不多说,来看看详细的介绍: MyCat 基本配置 首先针对多租户配置了多个数据库,在 MyCat 的 schema.xml 中配置了多个 schema. 在 server.xml 中配置了一个用户: 后面会使用 MyCat 注解(就是注释)方式根据不同的标识,将操作指向不同的数据库. 过滤器识别请求匹配对应的数据库 标识有很多种方式可以加以区分,下面使用最简单的一种,通过不同的二级域名进行识别.二级域名和数据库对应的

  • springboot多租户设计过程图解

    这篇文章主要介绍了springboot多租户设计过程图解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 1. 概述 根据不同用户的请求,选择不同的数据源,不同的数据源可以是Oracle.MySQL或者其它.用到的技术栈,没有什么复杂的技术,可以看到,依赖也就加了几个而已,如下: 2. 先睹为快 如下图,header中tenant为zhangsan,则使用db_oauth为数据源,tenant为lisi,则使用db_test为数据源,tenant

  • 详解基于Mybatis-plus多租户实现方案

    一.引言 小编先解释一下什么叫多租户,什么场景下使用多租户. 多租户是一种软件架构技术,在多用户的环境下,共有同一套系统,并且要注意数据之间的隔离性. 举个实际例子:小编曾经开发过一套支付宝程序,这套程序应用在不同的小程序上,当使用者访问不同,并且进入相对应的小程序页面,小程序则会把用户相关数据传输到小编这里.在传输的时候需要带上小程序标识(租户ID),以便小编将数据进行隔离. 当不同的租户使用同一套程序,这里就需要考虑一个数据隔离的情况. 数据隔离有三种方案: 1.独立数据库:简单来说就是一个

  • 利用EF6简单实现多租户的应用

    什么是多租户 网上有好多解释,有些上升到了架构设计,让你觉得似乎非常高深莫测,特别是目前流行的ABP架构中就有提到多租户(IMustHaveTenant),其实说的简单一点就是再每一张数据库的表中添加一个TenantId的字段,用于区分属于不同的租户(或是说不同的用户组)的数据.关键是现实的方式必须对开发人员来说是透明的,不需要关注这个字段的信息,由后台或是封装在基类中实现数据的筛选和更新. 基本原理 从新用户注册时就必须指定用户的TenantId,我的例子是用CompanyId,公司信息做为T

  • MybatisPlus 多租户架构(Multi-tenancy)实现详解

    在进行多租户架构(Multi-tenancy)实现之前,先了解一下相关的定义吧: 什么是多租户 多租户技术或称多重租赁技术,简称SaaS,是一种软件架构技术,是实现如何在多用户环境下(此处的多用户一般是面向企业用户)共用相同的系统或程序组件,并且可确保各用户间数据的隔离性. 简单讲:在一台服务器上运行单个应用实例,它为多个租户(客户)提供服务.从定义中我们可以理解:多租户是一种架构,目的是为了让多用户环境下使用同一套程序,且保证用户间数据隔离.那么重点就很浅显易懂了,多租户的重点就是同一套程序下

  • 详解在.net core中完美解决多租户分库分表的问题

    前几天有人想做一个多租户的平台,每个租户一个库,可以进行水平扩展,应用端根据登录信息,切换到不同的租户库 计划用ef core实现,他们说做不出来,需要动态创建dbContext,不好实现 然而这个使用CRL很轻松就能解决了 以下为演示数据库,有两个库testdb和testdb2,查询结果如下 目标: 根据传入登录信息连不不同的库,查询返回结果,如登录人为01,返回d1.default,登录人为02 返回 d2.default 实际上这个需求就是分库分表的实现,通过设置数据库/表映射关系,根据传

  • 详解ASP.NET Core中配置监听URLs的五种方式

    默认情况下,ASP. NET Core应用会监听一下2个Url: http://localhost:5000 https://localhost:5001 在本篇博文中,我将展示如何使用五种不同的方式改变应用监听的URLs. 在ASP.NET Core项目启动时,有多种配置监听Url的方式,在我之前的一篇博客中,已经展示了在ASP.NET Core 1.0中如何应用不同的方式配置,在ASP.NET Core 3.x中,大部分方式还是一样的. UseUrls() - 在Program.cs配置程序

  • 详解ASP.Net Core 中如何借助CSRedis实现一个安全高效的分布式锁

    引言:最近回头看了看开发的.Net Core 2.1项目的复盘总结,其中在多处用到Redis实现的分布式锁,虽然在OnResultExecuting方法中做了防止死锁的处理,但在某些场景下还是会发生死锁的问题,下面我只展示部分代码: 问题: (1)这里setnx设置的值"1",我想问,你最后del的这个值一定是你自己创建的吗? (2)图中标注的步骤1和步骤2不是原子操作,会有死锁的概率吗? 大家可以思考一下先,下面让我们带着这两个问题往下看,下面介绍一下使用Redis实现分布式锁常用的

  • 详解ASP.NET Core 中基于工厂的中间件激活的实现方法

    IMiddlewareFactory/IMiddleware是中间件激活的扩展点. UseMiddleware扩展方法检查中间件的已注册类型是否实现IMiddleware.如果是,则使用在容器中注册的IMiddlewareFactory实例来解析IMiddleware实现,而不使用基于约定的中间件激活逻辑.中间件在应用的服务容器中注册为作用域或瞬态服务. 优点: 按客户端请求(作用域服务的注入)激活 让中间件强类型化 IMiddleware按客户端请求(连接)激活,因此作用域服务可以注入到中间件

  • 详解ASP.NET Core 中的框架级依赖注入

    1.ASP.NET Core 中的依赖注入 此示例展示了框架级依赖注入如何在 ASP.NET Core 中工作. 其简单但功能强大,足以完成大部分的依赖注入工作.框架级依赖注入支持以下 scope: Singleton - 总是返回相同的实例 Transient - 每次都返回新的实例 Scoped - 在当前(request)范围内返回相同的实例 假设我们有两个要通过依赖注入来进行工作的工件: PageContext - 自定义请求上下文 Settings - 全局应用程序设置 这两个都是非常

  • 详解ASP.NET Core 中的多语言支持(Localization)

    首先在 Startup 的 ConfigureServices 中添加 AddLocalization 与 AddViewLocalization 以及配置 RequestLocalizationOptions (这里假设使用英文与中文): public void ConfigureServices(IServiceCollection services) { services.AddLocalization(options => options.ResourcesPath = "Reso

  • 详解Java删除Map中元素java.util.ConcurrentModificationException”异常解决

    今天在使用map并需要根据某些条件删除map元素时,自然而然想到调用Map中的remove(Object key)函数进行删除,代码如下: //遍历map,如果key<5,那么就删除此元素. Map<Integer, Integer> users = new LinkedHashMap<Integer, Integer>(); for (Map.Entry<Integer,Integer> entry : users.entrySet()){ for (int i

  • 详解mybatis-plus实体类中字段和数据库中字段名不对应解决办法

    在使用mybatis或者mybatis-plus时候,有些时候会出现数据库的字段名和实体类的字段名不一致的情况,如果运行那么这个字段就会无法进行自动映射而报错.这里就以我的数据库name字段名和这里的实体类的u_name字段名为例. 解决办法有以下三种 方法一: 将数据库中的字段和实体类中的字段名修改成一样的名字 方法二: 如果是自定以mapper.xml文件中手写的sql查询语句,可以给字段起一个别名例如这里就可以写成select name as u_name from- 方法三: 使用注解@

  • 详解asp.net core 依赖注入

    前言 好久没有写微博了,因为前段时间由于家庭原因决定从工作了3年多的北京转移到上海去.依赖注入在学习net core的时候也有写过类似的东西,只是实践的较少,结果来到上海新公司系统框架涉及到了这块知识点,所以在了解完自己的项目之后决定做一些相关的总结.接下来就让我们先来了解hewi依赖注入. 什么是依赖注入 依赖注入,全称是"依赖注入到容器", 容器(IOC容器)是一个设计模式,它也是个对象,你把某个类(不管有多少依赖关系)放入这个容器中,可以"解析"出这个类的实例

  • 详解Maven项目缺少Maven Dependencies解决方法总结

    一.今天搭建了一个maven项目,在pom.xml文件引入依赖后,发现项目结构中没有Maven Dependencies文件(下图),但是在java Build Path中又可以找到Maven Dependencies文件(如下图): 但是,pom.xml文件中添加的依赖jar包也不会自动下载到项目中,update Project也是一样,于是是网上查找了很多方法,尝试后都发现没有用,最终,查看自己的pom.xml文件,发现是在依赖前面写了<dependencyManagement>这个标签(

随机推荐