需要事务才能使用TranLock,明明用了 返回

SqlSugar
37 178
public async Task<(bool success, string msg)> TranAsync(Func<Task<(bool success, string msg)>> func)
        {
            string? msg;
            bool result = false;
            try
            {
                await _db.BeginTranAsync();
                var m = await func();
                await _db.CommitTranAsync();
                msg = m.msg;
                result = true;
            }
            catch (Exception e)
            {
                await _db.RollbackTranAsync();

                _logger.Log(LogLevel.Error, e, e.Message);
                msg = e.Message;
            }

            return new(result, msg);
        }

定义

protected BaseService(
            ISqlSugarClient db,
            IMapper mapper,
            ILogger logger
            )
        {
            _logger = logger;
            _db = db.AsTenant();
            _defaultDb = _db.GetConnectionScope("DefaultDb").CopyNew();
            _logDb = _db.GetConnectionScope("LogDb").CopyNew();
            _mapper = mapper;
        }

执行任何func()使用.TranLock(DbLockType.Wait)都会报错“需要事务才能使用TranLock”

热忱回答37

  • 管理员大大能不能回答一下?

    0 回复
  • 用这个东西需要事务

    0 回复
  • image.png

    0 回复
  • 你都copynew了就不在一个事务里面了

    0 回复
  • 直接在db上copynew呢?

    0 回复
  • @厂口日成:这种事务应该去掉copynew

    0 回复
  • image.png

    这个地方不应该有copyNew()

    0 回复
  • copynew出来的对象是不受主db事务控制的

    0 回复
  •  1.异步方法不写await 需要db替换成db.CopyNew() ,不想加CopyNew就需要排查是否有漏掉await,一个不能少。

     2.使用await 返回值必须有Task,不能是Void 这种(表达式返回值只能Task 例如 List.Foreach 可以用原生foreach替换List.Foreach) ,特别嵌套方法要认真找,不想找就CopyNew解决

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

    也就红色标题来的地方是需要用到copynew的其他方可以通过修改代码不需要copynew


    0 回复
  • @fate sta:我也不想有copynew,之前没有加的时候,经常出现各种异常问题

    0 回复
  • @厂口日成:看上面的文档处理,就3种情况

    0 回复
  • @fate sta:还有疑问可以提供可以重现DEMO

    0 回复
  • @fate sta:重现demo后端就是去掉copynew,然后前端在短时间内调用几个接口,就会出现有一两个接口报错。有三种:

    QQ图片20230516171004.jpg

    QQ图片20230516171228.jpg

    QQ图片20230516171011.png

    中文提示 :  连接数据库过程中发生错误,检查服务器是否正常连接字符串是否正确,错误信息:Unable to cast object of type 'Microsoft.Data.ProviderBase.DbConnectionClosedConnecting' to type 'Microsoft.Data.SqlClient.SqlInternalConnectionTds'.DbType=\"SqlServer\";ConfigId=\"DefaultDb\".\r\nEnglish Message : Connection open error . Unable to cast object of type 'Microsoft.Data.ProviderBase.DbConnectionClosedConnecting' to type 'Microsoft.Data.SqlClient.SqlInternalConnectionTds'.DbType=\"SqlServer\";ConfigId=\"DefaultDb\"

    前后端分离的情况下机会每次都有,偶尔有一次正常。

    0 回复
  • 直接用swagger界面单个点击测试没有这种情况

    0 回复
  • @厂口日成:需要提供完整DEMO 

    0 回复
  • 线程安全问题,只能放弃跨库事务了,我用apifox测试,开多个线程就能复现错误。

    0 回复
  • @厂口日成:你不提供代码我是没办法给你找问题的,肯定你用错了,目前所有用户只要提供DEMO 100%在我说的3条之内

    0 回复
  • 并且你提供DEMO自测能重现的

    0 回复
  • SqlSugarAsyncDemo.rar

    启动后用任意工具开多线程测试就可以复现结果,我开了5个线程。

    0 回复
  • image.png

    0 回复
  • 这个代码要这样改

    0 回复
  • 十万循环你插死了也插不完。要改成批量

    0 回复
  • 你测试应该用 正常数量的数据插入和查询,设置每1秒请求 200左右发请求,能重现的  

    0 回复
  • 不要测试插入啊,插入没有报错,就测试两个get就可以了

    image.png

    插入我手动运行了一次,多线程测试我只运行了上图这个,之前发的三个错误就会频繁出现,如果用copynew就没有问题

    0 回复
  • 找到问题了

    image.png

    这些建表代码不能写在这里面

    0 回复
  • 建库建表怎么写到每次请求里面

    0 回复
  • image.png

    0 回复
  • 不对你还有地方写错了

    0 回复
  • image.png

    要改成这个

    并且改成单例注入

    0 回复
  • SqlSugarScope 注入改成单例

    0 回复
  • image.png

    这个是错的,你虽然SqlSugarClient是AddScope,你每次都是拿 sqlugar这个对象 没有委托里面new 

    正确应该是 (i=>new SqlSugarClient)

    0 回复
  • 还有codefirst代码不要每次请求

    0 回复
  • AddScope (i=>new SqlSugarClient) 这是OK

    AddScope (i=>变量) 这是错误的 ,明白了吗 

    0 回复
  • 只有单例注入SqlSugarScope才能用变量

    0 回复
  • 建库建表是在每次启动的时候,后面那个我改一下试试

    0 回复
  • @厂口日成:建库和建表不能写在里面,每请求这样大量浪费性能你可以先注释掉

    0 回复
  • 好的

    0 回复