只要new就行了,SqlSugarClient不能存储于静态变量,保证每次请求都是new出来的
特别注意内部线程并发 并且(IsAutoCloseConnection=true 需要设置true)
和异步等不要少await等,适合有经验的用户(和Dapper EFCore玩法一样) 可以用var newdb=db.CopyNew()保证安全
也可以通过IOC 创建新实例(IOC对仓储这些更友好些)
异步知识: async void或者表达式的async Action是不受await等待效果的需要注意线程安全,只有 async Func<Task>有等待效果
sqlsugarclient就efcore、dapper一样的东西,他们怎么用,你也怎么用
内部开线程或者Job需要在创建新实例保证线程安全有2种方式:
1.IOC 创建新实例 点击查询 (推荐)
2.db.CopyNew 适合 【简单项目】 和 【只有个别方法报错或者报错频率不高懒的排查问题可以用这个】
注意:IsAutoCloseConnection=true 需要设置true
只需要看下面3条就行了,100%覆盖所有场景
排查1:异步方法wait存在漏写, 一个不能少 。解决方案:找到漏掉的await 建议补上遗漏的await,如果不想补就用db.CopyNew()。
排查2:使用await 返回值必须有Task,不能是Void 这种(表达式中异步只能是Func<Task>不能是Action<X> ,比如List.Forech就是Action要改普通forech) 建议改代码,如果不想修改 db改成db.CopyNew()解决
排查3:Task.WhenAll 、 ParallelAsync 和 第三方定时任务库 Job (backgroundservice也算) 使用 db.CopyNew()
方式1: 强制刷新AsyncLocal实现线程安全 点击查看 (优点支持仓储和封装代码)
方式2:db.CopyNew()强制线程安全,缺点不适合仓储和封装代码
CopyNew只有定时任务和Task.WhenAll 第3项必要需要加其他只要代码写对就不需要加
CopyNew要当前业务方法用,不能赋值全局变量,避免写到公用方法(会破坏事务会有问题)
CopyNew如果要用事务看3.1
多租户要用db.CopyNew().GetConnection方法(不能用GetConnectionScope)
上面提供的方案可以说99%覆盖,几年下来只要提测试用例的基可以说都上面的问题引起的
除了6以外,如果你不会排查就用笨方法
注意:禁止在公用方法使用CopyNew(),写到当前业务方法,公用方法不要写,这样事务不好维护
性能强大,等于原生new SqlConnection 和Dapper原理一样
//db使用CopyNew()
await DB.CopyNew().Queryable<Order>().ToListAsync();
//错误写法,因为CopyNew赋值给变量后,这个变量也要保证是线程安全的,尽量CopyNew在方法中使用
base.Conext=Db.CopyNew()//错误写法
//事务中要声名一个变量,CopyNew必须在当前方法使用
var newDb=DB.CopyNew();
newDb.BeginTran();
....
....
newDb.CommintTran();
//仓储 (请升级到5.1.4.78 之前版本有问题)
rep.CopyNew().Insert(p)// orm自带方法用这个
rep.CopyNew<自定义<类>>().MyXXX(p)//用到自定义仓储方法用这个
//多租户
//5.1.4.106
var newDb=db.CopyNew();
//正确
newDb.GetConnection("1")
//错误:租户CopyNew不要用Scope
newDb.GetConnectionScope("1")点对点的线程安全写法,该功能一般适合用在CopyNew()不方便改的情况
只能点对点的保证线程安全,就是这个接口单次请求不报错这个锁就有用
如果单次请求就报错那么这个锁就没有用,还有这个锁用的地方不要多
注意:锁的性有还是不错的,不过锁的实例是同一个,用的地方不能多(建议5个以下,只给特殊情况使用)
using (await db.AsyncLock())//默认30秒超时
{
//里面await不能少
await _Rep.InsertAsync(xx);
await _Rep.InsertAsync(yy);
}3.1和3.2 只有特殊场景才适合使用,特别是3.2能不用就不要用
2016 © donet5.comApache Licence 2.0