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 { get ; set ; } } //根據特性直接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 { get ; set ; } } [TenantAttribute( "2" )] public class C2Table { public string Id { get ; set ; } } |
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() |