偶发性错误,线程安全

 步骤1 (80%可以解决):

SqlSugarScope线程安全对象可能避免大多数的线程安问问题

1、SqlSugarClient换成SqlSugarScope  (SqlSugarScope  要用单例不然内存会增加)

2、多租户: db.GetConnection 换成 db.GetConnectionScope(Aop也要统一不然事件注册不了)

3、IsAutoCloseConnection=true 需要设置true

重点:SqlSugarScope一定要用单例


 步骤2 (1+2可以99%解决): 

如果按步骤1改了还报错那么肯定就下面3种情况:

4、异步方法wait存在漏写, 一个不能少 。不想找 就用db.CopyNew()。

5、使用await 返回值必须有Task,不能是Void 这种(表达式中异步只能是Func<Task>不能是Action<X>) ,特别嵌套方法要认真找,不想找就CopyNew解决

6、Task.WhenAll 、 ParallelAsync  和 第三方定时任务库    使用  db.CopyNew() 

 

 笨方法 (100%可以解决)

上面提供的方案可以说99%覆盖,几年下来只要提测试用例的基可以说都上面的问题引起的

除了6以外,如果你不会排查就用笨方法

 3.1 方式1: db.CopyNew() 

性能强大,等于原生new SqlConnection 和Dapper原理一样

 //db使用CopyNew()
 await DB.CopyNew().Queryable<Order>().ToListAsync();
 
 //仓储新版本 请升级到5.1.4.78 之前版本有问题
 rep.CopyNew().Insert(p)// orm自带方法用这个
 rep.CopyNew<自定义<类>>().MyXXX(p)//用到自定义仓储方法用这个

 3.2 方式2:异步锁

点对点的线程安全写法,该功能一般适合用在CopyNew()不方便改的情况

只能点对点的保证线程安全,就是这个接口单次请求不报错这个锁就有用

如果单次请求就报错那么这个锁就没有用,还有这个锁用的地方不要多

注意:锁的性有还是不错的,不过锁的实例是同一个,用的地方不能多(建议5个以下,只给特殊情况使用)

  using (await db.AsyncLock())//默认30秒超时
  {
      //里面await不能少
      await _Rep.InsertAsync(xx);
      await _Rep.InsertAsync(yy);
   }

3.1和3.2 只有特殊场景才适合使用,特别是3.2能不用就不要用

文档:SqlSugar5.0