SqlSugar多庫/多租戶

1、 多庫和多租戶

如果是接口ISugarClient先看一下標題6,看完在看這兒

1.1 固定多數據庫模式

數據庫數量是固定的一般在聲明的全部加上

//通過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  }
});
 
 
 //定義實體對應ConfigId ,下面0表示ConfigId爲0的數據庫
 [TenantAttribute("0")]//對應ConfigId
 public class C1Table
 {
   public string Id { getset; }
 }
     
 
//根據特性直接CRUD 
var list=db.QueryableWithAttr<Order>().ToList();//5.0.9.1 全自動切換庫查詢
var  list1=db.AsTenant().QueryableWithAttr<Order>().ToList();//接口需要AsTenant()轉成租戶
var  list2=db.Queryable<Order>().AsWithAttr().ToList();//強制名庫+表名一般在嵌套或者unionall不能切換庫中用
db.InsertWithAttr(list).ExecuteCommand() ;//5.0.9.1 全自動切換庫插入
db.UpdateWithAttr(list).ExecuteCommand() ;//5.0.9.1 全自動切換庫更新
db.DeleteableWithAttr(list).ExecuteCommand() ;//5.0.9.1 全自動切換庫刪除
 
//根據特性獲取獲取db
var childDb=db.GetConnectionWithAttr<C2Table>();//線程安全用GetConnectionWithAttrScope
var list=childDb.Queryable<Order>().ToList();
 
//手動獲取db
var childA=db.GetConnection("0");//線程安全用GetConnectionScope
var list=childA.Queryable<Order>().ToList();
 
//事務直接用就行,支持回滾(標題3有原理介紹)

1.2 動態多數據庫模式

就是一個用戶對應一個庫,或一個企業對應一個數據庫,通過後臺維護用戶和數據庫的方式

 //當前上下文不存在則添加 
 if(!db.IsAnyConnection(configId))
    //添加一個db到當前上下文 (Add部分不線上下文不會共享)
    db.AddConnection(new ConnectionConfig(){
                DbType = SqlSugar.DbType.SqlServer,
                ConfigId = "1",//設置庫的唯一標識
                IsAutoCloseConnection = true,
                ConnectionString = Config.ConnectionString2 });
                 
  var currentDb=db.GetConnection(configId);//獲取當前上下文存在的db             
                 
 //單例SqlSugarScope中用AddConnection和IsAnyConnection多用戶不會相互影響,不會共享

Saas分庫詳解:https://www.donet5.com/Home/Doc?typeId=2403

 

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  根據特性獲取(推薦)

適合一個實體和庫是一對一的情況

var db = new SqlSugarClient(new List<ConnectionConfig>()
{
 new ConnectionConfig(){ConfigId="1",DbType=DbType.SqlServer,ConnectionString=..,IsAutoCloseConnection=true},
 new ConnectionConfig(){ConfigId="2",DbType=DbType.MySql,ConnectionString=..,IsAutoCloseConnection=true  
});
 
//根據特性獲取獲取db
var childDb=db.GetConnectionWithAttr<C2Table>();
childDb.Queryable<Order>().ToList();
 
 
//根據特性直接CRUD
var list=db.QueryableWithAttr<Order>().ToList();//5.0.9.1 全自動切換庫查詢
var  list2=db.Queryable<Order>().AsWithAttr().ToList();//強制名庫+表名一般在嵌套或者unionall不能切換庫中用
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 { getset; }
  }
    
  [TenantAttribute("2")]
  public class C2Table
  {
      public string Id { getset; }
  }

 2.3  通過切換數據庫(不推薦)

切換對設計要求過高,很容切了忘記切回來, 特別是一個請求多次切換

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  }
});
 
//使用默認數據庫對象
db.Deleteable<Order>().ExecuteCommand();
 
//切換主db默認值數據庫 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在多租戶是不共享的,需要單獨設置,滿足更多需求,你可以循環添加

//注意: 
//如果你用的 GetConnectionScope或者 GetConnectionScopeWithAttr AOP也應該用 GetConnectionScope 
//如果你用的 GetConnection或者 GetConnectionWithAttr AOP也應該用 GetConnectionScope 
  
  
  SqlSugarClient Db= new SqlSugarClient(new ConnectionConfig(){
           ConnectionString = "連接符字串"
           DbType = DbType.SqlServer,
           IsAutoCloseConnection = true},
           db=>{  
                    //也可以這裏面循環
                   db.GetConnection("1").Aop.OnLogExecuting = (sql, pars) =>
                   {
                     Console.WriteLine("執行1庫"+sql);
                   };
                   db.GetConnection("0").Aop.OnLogExecuting = (sql, pars) =>
                   {
                      Console.WriteLine("執行0庫"+sql);
                   };
   
  });

 

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()

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章