仓储+多租户

1、创建数据库对象

创建一个相同上下文共享的 数据库操作对象

//单例不要写在泛型类中, 类<T>.Db 这种是无效单例 ,T不同就会有多个实例
public SqlSugarScope Db= new SqlSugarScope (new List<ConnectionConfig>()
{
  new ConnectionConfig(){ConfigId="0",DbType=DbType.SqlServer,ConnectionString="..",IsAutoCloseConnection=true},
  new ConnectionConfig(){ConfigId="1",DbType=DbType.MySql, ConnectionString="...",IsAutoCloseConnection=true}
 //ConfigId用来区别是哪个库
}
,db=>
{
       //如果是GetConnectionScope或者GetConnectionScopeWithAttr这边也应该是GetConnectionScope
       //如果用的是GetConnection或者GetConnectionWithAttr这边也应该是GetConnection
       //用哪个就AOP添加哪个
       //技巧:这边可以循环处理这个更方便些
       db.GetConnection("0").Aop.OnLogExecuting = (sql, p) =>
       {
          Console.WriteLine(sql);
       };
       db.GetConnection("1").Aop.OnLogExecuting = (sql, p) =>
       {
          Console.WriteLine(sql);
       };
       //如果是 日志库 不要加AOP防止AOP循环引用
}
);
//单例注入(因为是SqlSugarScope应该单例)
services.AddSingleton<ISqlSugarClient>(Db);
//如果是SqlSugarClient不能单例

如果用IOC看下面注用法


2、创建仓储

2.1 方法说明

每个GetConnection出来的数据库是独立的数据库操作对象,可以一起使用相互没有任何影响

   //方式1:通过Config获取数据库,比较灵活
   var db1=db.GetConnection(configId) //非线程安全
   var db1=db.GetConnectionScope(configId); //线程安全 (5.0.7.7)
      
      
   //方式2:通过特性获取数据库,一个实体对一个库的时候非常方便
   var db2=db.GetConnectionWithAttr<T>() //非线程安全
   var db2=db.GetConnectionScopeWithAttr<T>() //线程安全(5.0.7.7)
      
   [TenantAttribute("1")]//对应ConfigId=1
    public class C1Table
    {
     public string Id { get; set; }
    }

接口说明:

ISqlSugarClien childDb=Db.GetConnection("1");//子Db负责CRUD(没有实现ITenant接口)
ITenant tenant=Db;//租户负责多库事务和管理子Db
 
//完整Db的接口关系 
SqlSugarScope: ISqlSugarClient, ITenant
SqlSugarClient: ISqlSugarClient, ITenant

2.2 仓储用例

public class Repository<T> : SimpleClient<T> where T : class, new()
{
    public ITenant itenant = null;//多租户事务、GetConnection、IsAnyConnection等功能
    public Repository() 
    {
    
    
       //方式1:.NET CORE自带的IOC 会封装的人用
      //需要将注入时用到的Services存到一个静态对象中通过Services获取  
      base.Context=存储的Services.GetService<ISqlSugarClient>().GetConnectionScopeWithAttr<T>(); 
      //GetConnectionScope(configId)也可以 2.1已介绍了他们区别
      itenant=存储的Services.GetService<ISqlSugarClient>().AsTenant();//处理事务
      
      //说明:为什么不用构造函数注入,如果你不用切换仓储方法可以用构造函数注入,如果切换仓储就需要非构造注入
      
      
      
      //方式2:SqlSugar.Ioc用法
      base.Context =DbScoped.SugarScope.GetConnectionScopeWithAttr<T>();//子Db无租户方法,其他功能都有
      //base.Context =DbScoped.SugarScope.GetConnectionScope(configId);  也可以手动获取
      itenant = DbScoped.SugarScope;//处理多租户事务、GetConnection、IsAnyConnection等功能
      
      
      //方式3:Furion框架中用
      base.Context=  App.GetService<ISqlSugarClient>().AsTenant().GetConnectionScopeWithAttr<T>(); 
      itenant = App.GetService<ISqlSugarClient>().AsTenant(); 
       
       
      //方式4:不用Ioc
      base.Context=单例的SqlSugarScope.GetConnectionScopeWithAttr<T>();
      itenant=单例的SqlSugarScope;
      
      
    }

}

base.Context=具体数据库对象 可以使用仓储方法在具体数据库进行CRUD

itenant =完整数据库对象  管理多个仓储事务等、还能在使用GetConnection、IsAnyConnection等功能


3、使用仓储+事务

3.1通过继承使用

通过base.仓储方法进行CRUD, itenant负责事务

仓储有哪些方法可以看仓储入门:https://www.donet5.com/Home/Doc?typeId=1228

public class UserRepository 
{
      private readonly Repository<Abpusers> rep;//想写几个就写几个
 
        public UserService()
        {
            rep= new Repository<Abpusers>();
        }
 
 
    //使用事务
    public void TestTran()
    {
        try
        {
            rep.itenant.BeginTran();

            rep.Insert(new UserInfo() {... });
            var orderDal= rep.ChangeRepository<Repository<Order>>();//切换仓储
            orderDal.Insert(new Order() {... });
            orderDal.Context.XXXXX

            rep.itenant.CommitTran();
        }
        catch (Exception ex)
        {
            rep.itenant.RollbackTran();
            throw ex;
        }
    }
}

3.2 直接使用

var orderDal=db.GetRepository<Repository<Order>>();)
 
//使用仓储方法
orderDal.Insert(data);


4、切换仓储

  var orderItemDb = rep.ChangeRepository<Repository<OrderItem>>();;


5、线程安全

用SqlSugarScope的注意了获取子对象线程安全用法如下

 新功能(5.0.7.7preview03+):

this.Context=db.GetConnectionScope(1);//线程安全,子对象也支持了线程安全
this.Context=db.GetConnection(1);//非线安全对象 ,this类需要new ,内部开线程需要new this类


6、工作单元

上面主要是原理和实现比较灵活,你也可以用我封好的工作单元 5.0.8.3支持

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


文档:SqlSugar5.0