创建一个相同上下文共享的 数据库操作对象
//注册上下文: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;
});注意:仓储对象不能单例注入
每个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, ITenantpublic 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等功能
通过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;
}
}
}var orderDal=db.GetRepository<Repository<Order>>();) //使用仓储方法 orderDal.Insert(data);
如果是多仓储注入就可以不用切换仓储,如果你非要用切换仓储写法如下
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处理事务
}
}用SqlSugarScope的注意了获取子对象线程安全用法如下
新功能(5.0.7.7preview03+):
this.Context=db.GetConnectionScope(1);//线程安全,子对象也支持了线程安全 this.Context=db.GetConnection(1);//非线安全对象 ,this类需要new ,内部开线程需要new this类
上面主要是原理和实现比较灵活,你也可以用我封好的工作单元 5.0.8.3支持
https://www.donet5.com/Home/Doc?typeId=2360
2016 © donet5.comApache Licence 2.0