仓储+多租户

1、注入多库Db

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

//注册上下文:AOP里面可以获取IOC对象,如果有现成框架比如Furion可以不写这一行
services.AddHttpContextAccessor();

//注册SqlSugar
services.AddSingleton<ISqlSugarClient>(s =>
{
    //单例不要写在泛型类中, 类<T>.Db 这种是无效单例 ,T不同就会有多个实例
  SqlSugarScope Db= new SqlSugarScope (new List<ConnectionConfig>()
   {
      new ConnectionConfig(){ConfigId="0",DbType=DbType.SqlServer,....},
      new ConnectionConfig(){ConfigId="1",DbType=DbType.MySql,.....}
    //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);
       };
       
       
       //获取IOC对象不要求在一个上下文
       //vra log=s.GetService<Log>()
                
       //获取IOC对象要求在一个上下文
       //var appServive = s.GetService<IHttpContextAccessor>();
       //var log= appServive?.HttpContext?.RequestServices.GetService<Log>();
    });
    return Db;
});

2、创建多库仓储

注意:仓储对象不能单例注入

2.1 方法说明

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

   //方式1:通过Config获取数据库,比较灵活
   var db1=db.GetConnection(configId) //非线程安全 (性能好)
   var db1=db.GetConnectionScope(configId); //线程安全 (解决大部线程安全,性能有些损耗)
      
      
   //方式2:通过特性获取数据库,一个实体对一个库的时候非常方便
   var db2=db.GetConnectionWithAttr<T>() //非线程安全  (性能好)
   var db2=db.GetConnectionScopeWithAttr<T>() //线程安全 (解决大部线程安全,性能有些损耗)
      
   [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(ISqlSugarClient db) 
    {
    
         itenant=db.AsTenant();//用来处理事务
         base.Context=db.AsTenant().GetConnectionWithAttr<T>();//获取子Db
         //GetConnectionScopeWithAttr (解决大部线程安全,性能有损耗)
         
         
         //如果不想通过注入多个仓储
         //用到ChangeRepository或者Db.GetMyRepository需要看标题4写法
         
     
    }

}

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(Repository<Abpusers> iocrep)
       {
           this.rep=iocrep;
           //IOC仓储配置
           //builder.Services.AddScoped(typeof(Repository<>));
       }
 
 
    //使用事务
    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>>();
 
 
public class Repository<T> : SimpleClient<T> where T : class, new()
{
    
    Itenant itenant=null;//主db处理事务
    public Repository() 
    {
    
       //多库下使用该功能需要非构造函数注入
       var db=你存储的Services.BuildServiceProvider()
                    .GetService<ISqlSugarClient>();
       //教程:https://www.donet5.com/Doc/27/2563
 
       base.Context=db.GetConnectionScopeWithAttr<T>(); //仓储使用当前T的Db
       this.itenant=db;//主db处理事务
   }
}

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

7、DEMO下载

SqlSugarDemo.zip


关闭
果糖网