.NET SAAS 架構與設計 -SqlSugar ORM

果糖大資料科技發表於2021-12-05

1、資料庫設計

常用的Saas分庫分為2種型別的庫 

1.1 基礎資訊庫

主要存組織架構 、許可權、字典、使用者等 公共資訊 

效能優化:因為基礎資訊庫是共享的,所以我們可以使用 讀寫分離,或者二級快取來進行效能上的優化

2.2 業務庫

我們要進行的分庫都基於業務庫進行分庫,例如 A集團使用 A01庫 ,B集團使用B01庫 ,也可以多個小集團使用一個 資料庫

如下:

 業務庫1   :集團A

 業務庫2  :    集團B, 集團F

 業務庫3 :     集團C, 集團D, 集團E

效能優先:因為合理的進行了分庫,所以在效能上並沒有什麼瓶頸,並且資料庫可以扔到不同的伺服器上

2、表設計

下面的表設計的比較簡單,主要是通過使用者可以拿到當前使用者的連線字串,然後進行資料庫操作

2.1 資料庫配置表    

主鍵、資料庫連線資訊、集團ID  (基礎資訊庫)

2.2 使用者表  

主鍵、使用者名稱、密碼、集團ID (基礎資訊庫)

 

3、程式碼編寫

下面的程式碼很簡單,我們通了多租戶方式實現了動態根據使用者獲取不同的業務庫

操作業務庫我們使用   DbManger.BizDb

操作基礎資訊庫我們使用 DbManger.MasterDb

如果我們要用到事務就用  DbManger.Db 

 /// <summary>
    /// 資料庫管理
    /// </summary>
    public class DbManger
    {
 
       /// <summary>
       /// 獲取業務庫物件
       /// </summary>
        public static ISqlSugarClient BizDb 
        {
            get 
            {
                UserInfo user = GetUserInfo();//獲取使用者資料庫連線字串資訊
                var configId = user.OrgId.ToString();//集團ID(也可以叫租戶ID)
                if(!Db.IsAnyConnection(configId)){
                      Db.AddConnection(new ConnectionConfig() { 
                        ConfigId = configId, 
                        ConnectionString = "DataSource=" + user.Connection, 
                        DbType = DbType.SqlServer,
                         IsAutoCloseConnection = true });
                }      
                var result=Db.GetConnection(configId);
               //可以給業務庫result設定AOP
                return result;
            }
        }
 
 
        /// <summary>
        /// 基礎資訊庫
        /// </summary>
        public static ISqlSugarClient MasterDb
        {
            get
            {
                //如果是跨服務庫分庫,也需要動態配置的,因為庫的IP會變
                //參考業務庫用法
                return Db.GetConnection("default");
            }
        }
 
 
        /// <summary>
        /// 利用SqlSugarScope單例+多租戶來處理多庫事務
        /// </summary>
        public static SqlSugarScope Db =new SqlSugarScope(new ConnectionConfig()
        {
            ConfigId="default",
            DbType = SqlSugar.DbType.SqlServer,
            ConnectionString =  @"基礎資訊庫連線字串",
            IsAutoCloseConnection = true
        },
         db =>
         {
             //基礎庫AOP
             db.Aop.OnLogExecuting = (s, p) =>
             {
                            
             };
 
         });
 
        /// <summary>
        /// 獲取使用者資料庫連線字串資訊
        /// </summary>
        /// <returns></returns>
        private static UserInfo GetUserInfo()
        {
            throw new System.NotImplementedException();
        }
 
    }

使用用例,繼承後直接使用

 public class OrderManger: DbManger
    {
        public void Test() 
        {
            try
            {
                Db.BeginTran();//用Db管理 MasterDb和BizDb事務
 
 
                MasterDb.Insertable(xxx).ExecuteCommand();//操作基礎資訊庫
                BizDb.Insertable(xxx).ExecuteCommand();//操作業務庫
 
 
                Db.CommitTran();//統一事務
    
             }
            catch (System.Exception ex)
            {
                Db.RollbackTran();
                throw ex;
            };
        }
    }

  

4、跨庫查詢

4.1 跨庫同伺服器

跨庫查詢我們要用BizDb進行查詢,因為BizDb是多變的,而MasterDb是固定的,查詢用BizDb為主

    var List = BizDb.Queryable<Order>()
            .LeftJoin<Custom>((o, cus) => o.CustomId == cus.Id)
            .AS<Custom>("SQLSUGAR4XTEST.dbo.Custom") //主表用AS("") 從表用AS<T>("")
            .Where(o => o.Id == 1)
            .Select((o, cus) => new ViewOrder { Id = o.Id, CustomName = cus.Name })
            .ToList();

生成的SQL如下:

SELECT  [o].[Id] AS [Id] ,
        [cus].[Name] AS [CustomName]  
FROM [Order] o 
Left JOIN [SQLSUGAR4XTEST].[dbo].[Custom] cus --生成的Sql就多了庫名
ON ( [o].[CustomId] = [cus].[Id] )   WHERE ( [o].[Id] = @Id0 )

注意:上面的例子是SqlServer跨庫查詢的用法,不同的資料庫跨庫查詢用法不一樣

 更多用法: https://www.donet5.com/Home/Doc?typeId=2244

4.2跨庫不同伺服器

因為我們基礎資訊庫是固定的,所以我們可以把基礎資訊庫,同步到不同的伺服器上,通過讀分離的方式 ,那麼每個業務伺服器都會有一個

基礎資訊庫了,然後在通過4.1的方式實現

 

5、業務表建立

我們可以通過CodeFirst建立業務庫和表

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

 

7、表過濾

一個業務庫中的表對應多個集團,那我們設計表的時候肯定有個 OrgId或者租戶ID進行資料表區別

我們需要將DbManger.bizDb進行修改,新增相應的表過濾器如果表中有OrgId的就可以新增過濾器

/// <summary>
/// 獲取業務庫物件
/// </summary>
public static ISqlSugarClient BizDb 
{
    get 
    {
         UserInfo user = GetUserInfo();//獲取使用者資料庫連線字串資訊
         var configId = user.OrgId.ToString();//集團ID(也可以叫租戶ID)
         if(!Db.IsAnyConnection(configId)){
               Db.AddConnection(new ConnectionConfig() { 
                        ConfigId = configId, 
                        ConnectionString = "DataSource=" + user.Connection, 
                        DbType = DbType.SqlServer,
                         IsAutoCloseConnection = true });
           } 
                 
          var result=Db.GetConnection(configId);
          result.QueryFilter.Add(new TableFilterItem<Order>(it => it.OrgId==configId);//新增表過濾器
         //可以多個表
          
         return result;
    }
}

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

8、高安全性日誌

我們可以通過差異日誌拿到資料更變記錄,記錄到日誌,SAAS操作一些核心資料差異日誌肯定少不了,安全係數高

db.Aop.OnDiffLogEvent = it =>
{
                //操作前記錄  包含: 欄位描述 列名 值 表名 表描述
                var editBeforeData = it.BeforeData;
                //操作後記錄   包含: 欄位描述 列名 值  表名 表描述
                var editAfterData = it.AfterData;
                var sql = it.Sql;
                var parameter = it.Parameters;
                var data = it.BusinessData;//這邊會顯示你傳進來的物件
                var time = it.Time;
                var  diffType=it.DiffType;//enum insert 、update and delete  
                   
                //Write logic
};
 
db.Insertable(new Student() { Name = "beforeName" })
.EnableDiffLogEvent() //注意需要加上啟用日誌,可以傳引數
.ExecuteReturnIdentity(); 

具體用法:https://www.donet5.com/Home/Doc?typeId=1204

 

9、總結

SAAS架構用到技術基本上都是現有功能,我這一篇文章相當於一個彙總,本人也做了6年SAAS架構,至少目前的方案是成熟方案 ,並且有產品驗證並且上線運營,如果有更好的建議可以回覆,或者直接找我溝通

原始碼下載: https://github.com/donet5/sqlsugar

Nuget: 安裝SqlSugarCore

相關文章