• .NET SAAS 架构与设计 SqlSugar ORM


    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

  • 相关阅读:
    一次开发中使用过的shell命令
    MySQL 数据库 Having 和Where的区别
    mysql 正则表达式
    mysql union与 union all 的区别
    压缩与解压
    MySQL Shell
    MGR监控报警
    MySQL Router单点隐患通过Keepalived实现
    expdp和impdp
    ogg trail文件序列号不一致
  • 原文地址:https://www.cnblogs.com/sunkaixuan/p/15646322.html
Copyright © 2020-2023  润新知