多租户、多数据库

1、 创建多库

如果是接口ISugarClient先看一下标题6,看完在看这儿

//通过ConfigId进行数据库区分
var db = new SqlSugarClient(new List<ConnectionConfig>()
{
 new ConnectionConfig(){ConfigId="0",DbType=DbType.SqlServer,ConnectionString=..,IsAutoCloseConnection=true},
 new ConnectionConfig(){ConfigId="1",DbType=DbType.MySql,ConnectionString=..,IsAutoCloseConnection=true  }
});

  

 //可以动态Add
 if(!db.IsAnyConnection(configId))//当前上下文不存在则添加
    db.AddConnection(new ConnectionConfig(){
                DbType = SqlSugar.DbType.SqlServer,
                ConfigId = "1",//设置库的唯一标识
                IsAutoCloseConnection = true,
                ConnectionString = Config.ConnectionString2 });
                
 //单例SqlSugarScope中用AddConnection和IsAnyConnection多用户不会相互影响,不会共享             
 //详细介绍:https://www.donet5.com/Home/Doc?typeId=2403
 
 
 //如果用的是接口请加个AsTenant才能调用租户方法
 //db.AsTenant().GetConnection(1)


2、如何使用多库

 2.1  子db操作多库 (推荐

优点灵活,在库的数据不确定的情况下可以使用,比如SAAS分库结合AddConnection和IsAnyConnection使用

主db

SqlSugarClient或者SqlSugarScope我们称为主db

拥租户方法有:db.BeginTran(事务)、db.GetConnection(获取子Db)等

在多租户中一般只用来 处理事、创建子DB和获取子DB

可以用 ISqlSugarClien或者ITenant 接收

ISqlSugarClient.AsTenant() 可以转成  ITenant  调用租户方法

子db 

通过租户方法GetConnection出来的我们称为子db,没有租户事务相关方法

我们一般用子db去操作指定ConfigId数据库 

可以用 ISqlSugarClient 接收,不能转成租户对象 没有租户方法

//主db
var db = new SqlSugarClient(new List<ConnectionConfig>()
{
 new ConnectionConfig(){ConfigId="A",DbType=DbType.SqlServer,ConnectionString=..,IsAutoCloseConnection=true},
 new ConnectionConfig(){ConfigId="B",DbType=DbType.MySql,ConnectionString=..,IsAutoCloseConnection=true  },
 new ConnectionConfig(){ConfigId="C",DbType=DbType.MySql,ConnectionString=..,IsAutoCloseConnection=true  }
});

//获取子Db
var childA=db.GetConnection("A");
var childB=db.GetConnection("B");
var childC=db.GetConnectionScope("C");//线程安全

//使用子Db用 
childA.Queryable<Order>().ToList(); 
childB.Queryable<Order>().ToList(); 

//事务看标题3
//线程安全 (推荐)
 //线程安全

 2.2  根据特性获取(推荐

适合一个实体和库是一对一的情况

//根据特性获取获取db
var list=db.GetConnectionWithAttr<C2Table>().Queryable<Order>().ToList();


//根据特性直接CRUD
var list=db.QueryableWithAttr<Order>().ToList();//5.0.9.1 全自动切换库查询
db.InsertWithAttr(list).ExecuteCommand() ;//5.0.9.1 全自动切换库插入
db.UpdateWithAttr(list).ExecuteCommand() ;//5.0.9.1 全自动切换库更新
db.DeleteableWithAttr(list).ExecuteCommand() ;//5.0.9.1 全自动切换库删除

//如果一个实体对应多个库看SAAS分库文档

//事务看标题3
 
 
  [TenantAttribute("1")]//对应ConfigId
  public class C1Table
  {
     public string Id { get; set; }
  }
   
  [TenantAttribute("2")]
  public class C2Table
  {
      public string Id { get; set; }
  }

 2.3  通过切换数据库(不推荐

切换对设计要求过高,很容切了忘记切回来, 特别是一个请求多次切换

//使用默认数据库对象
db.Deleteable<Order>().ExecuteCommand();

//切换数据库 ConfigId = 1
db.ChangeDatabase("1"); //改变db.的默认数据库

db.Deleteable<Order>().ExecuteCommand();


3、多库事务 

支持多库、跨服务器和多种数据库混合使用(老版本db.GetConnection要在事务外声名,然后在事务内用变量)

//开启事务
try {

 db.BeginTran(); //不能是db.Ado.BeginTran 

 db.GetConnection("1").Insertable(new Order()
 {
   CreateTime = DateTime.Now,
   CustomId = 1,
   Name = "a",
   Price = 1
 }).ExecuteCommand();

 db.GetConnection("2").Insertable(new Order()
 {
   CreateTime = DateTime.Now,
   CustomId = 1,
   Name = "a",
   Price = 1
 }).ExecuteCommand();

 //提交事务 
 db.CommitTran(); //不能是db.ado.CommitTran

}
catch(Exception ex)
{
  //回滚事务
  db.Rollback();
}

 
 
//主db
//注入的SqlSugarClient或者SqlSugarScope我们称为主db

//子db 
//通过租户方法GetConnection出来的我们称为子db,用来操作当前数据库,没有租户事务相关方法

//主db可以用事务管理多个子db ,也可以使用 GetConnection等租户方法



//目前底层是业务执行成功后统一提交事务,业务只要失败全部回滚,统一回滚过程中都有有3次重试回滚
//从目前用户使用情况来看,相当稳定几乎没有一例失败的反馈
//高安全级别数据:请使用差异日志+Catch(AggregateException ex)进行补偿机质
//如果回滚失败会throw new AggregateException


4、多租户设置AOP

AOP在多租户是不共享的,需要单独设置,满足更多需求,你可以循环添加

 db.GetConnection("A").Aop.OnLogExecuting = (sql, pars) =>
 {
     Console.WriteLine("执行1库"+sql);
 };
 db.GetConnection("B").Aop.OnLogExecuting = (sql, pars) =>
 {
     Console.WriteLine("执行0库"+sql);
 };
 //如果是SqlSugarScope请写在全局配置点里面(入门篇有介绍)


5、对表进行过滤

db.GetConnection("A").QueryFilter.Add(new TableFilterItem<Order>(it => it.Name.Contains("a"),true)
db.GetConnection("B").QueryFilter.Add(new TableFilterItem<Order>(it => it.Name.Contains("a"),true)

如果要对表进行数据隔离可以看 查询过滤器的例子

https://www.donet5.com/Home/Doc?typeId=1205


6、ISugarClient使用多租户

问题:Db.GetConnection点不出来,出现这种情况一般是用的接口对象ISqlSugarClient

解决方案: Db.AsTenant().GetConnection(1) 

原理如下:

ISqlSugarClient和SqlSugarClient不同,ISqlSugarClient不包含租户方法,原因如下

SqlSugarClient : ISqlSugarClient, ITenant //ISqlSugarClient和ITenant是平行关系,没有租户方法

我们可以通过自带转换实现

ISqlSugarClient db= 注入db ;
db.AsTenant().BeginTran();
db.AsTenant().CommitTran();
db.AsTenant().RollbackTran();
db.AsTenant().GetConnection(1)
db.AsTenant().IsAnyConnection(1)
//低版本 (db as ITenant).BeginTran()



文档:SqlSugar5.0