多线程报异常问题 返回

SqlSugar
4 151

麻烦问一下大家,我有个基于 .NET 6 Worker Service 的程序,需要分别从多个 WebService 中获得最新的数据存到数据库中,我想用多线程实现,结果一直异常,还请大家帮忙看下是咋回事。


现在的代码是可以运行的,但是如果我把 1 和 3 位置的 CopyNew 去掉,并且将事务处理换成 _dbClient.AsTenant().BeginTran 和 _dbClient.AsTenant().CommitTran 后,就会在 2 的位置报 “Index was out of range. Must be non-negative and less than the size of the collection. (Parameter 'index')”异常,同时在 4 处报 “Object reference not set to an instance of an object.”,这是为啥呢?


...

// SqlSugar 客户端
public static ISqlSugarClient _dbClient = new SqlSugarScope(new List<ConnectionConfig>
{
    new()
    {
        ConfigId = CommonConstants.DB_ID,
        DbType = DbType.Oracle,
        ConnectionString = _connStrs[CommonConstants.DB_ID],
        IsAutoCloseConnection = true,
        ConfigureExternalServices = new ConfigureExternalServices
        {
            EntityService = (c, p) =>
            {
                if (new NullabilityInfoContext().Create(c).WriteState is NullabilityState.Nullable)
                    p.IsNullable = true;
            }
        }
    },
    new()
    {
        ConfigId = CommonConstants.LOCAL_LOGGING_DB_ID,
        DbType = DbType.Sqlite,
        ConnectionString = _connStrs[CommonConstants.LOCAL_LOGGING_DB_ID],
        IsAutoCloseConnection = true,
        ConfigureExternalServices = new ConfigureExternalServices
        {
            EntityService = (c, p) =>
            {
                if (new NullabilityInfoContext().Create(c).WriteState is NullabilityState.Nullable)
                    p.IsNullable = true;
            }
        }
    }
}, db =>
{
    db.GetConnection(CommonConstants.LOCAL_LOGGING_DB_ID).Aop.OnLogExecuting = (sql, parameters) =>
    {
        _logger.Debug($"{CommonConstants.LOCAL_LOGGING_DB_ID} 准备执行语句:{sql}");
        _logger.Debug(string.Join(", ", parameters.Select(p => $"{p.ParameterName} = {p.Value}").ToList()));
    };
    db.GetConnection(CommonConstants.DB_ID).Aop.OnLogExecuting = (sql, parameters) =>
    {
        _logger.Debug($"{CommonConstants.DB_ID} 准备执行语句:{sql}");
        _logger.Debug(string.Join(", ", parameters.Select(p => $"{p.ParameterName} = {p.Value}").ToList()));
    };
});

...

protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
    while (!stoppingToken.IsCancellationRequested)
    {
        var taskList = new List<Task>();
        try
        {
            foreach (var svcInfo in _ifInfos)
            {
            
                if (svcInfo.svcType is "SomeType")
                    taskList.Add(Task.Factory.StartNew(() =>
                        SyncReport<SomeEntity>(svcInfo.svcID, svcInfo.svcAddress, svcInfo.svcOtherParam), stoppingToken));
                else if (headerInfo.ServiceType is "OtherType")
                {
                    taskList.Add(Task.Factory.StartNew(
                        () => SyncReport<OtherEntity>(svcInfo.svcID, svcInfo.svcAddress, svcInfo.svcOtherParam), stoppingToken));
                    taskList.Add(Task.Factory.StartNew(
                        () => SyncReport<AnotherEntity>(svcInfo.svcID, svcInfo.svcAddress, svcInfo.svcOtherParam), stoppingToken));
                }
            }

            await Task.WhenAll(taskList);
        }
        catch (Exception e)
        {
            _logger.LogError("在执行导入任务时发生异常:{}", e.Message);
        }
        finally
        {
            taskList.Clear();
        }
    }
}

private void SyncReport<T>(long svcId, string svcAddr, string para)
        where T: BaseEntity, new()
{
    ...
    
    try
    {
        var logDb = _dbClient.AsTenant().GetConnectionScope(CommonConstants.LOCAL_LOGGING_DB_ID).CopyNew();  // <---- 1
        
        var lastReportTime = db.Queryable<dynamic>()  // <----------------------------------------------------------- 2
            .Select(it => new
                { last_date = SqlFunc.MappingColumn(default(DateTime?), "MAX(`LOG_TIME`)") })
            .Where("`SVCID` = @SVCID", new { SVCID = svcId })
            .First();

        var dataList = ...; // <-- 根据上面获取到的最后记录时间,调用 WebService 获取最新的数据
        
        var db = _dbClient.AsTenant().GetConnectionScope(CommonConstants.DB_ID).CopyNew();  // <--------------------- 3
        
        foreach (var data in dataList)
        {
            //_dbClient.AsTenant().BeginTran();
            logDb.BeginTran();
            db.BeginTran();
            try
            {
                if (!db.Queryable<T>().WhereClassByPrimaryKey(data).Any())
                {
                    db.Insertable(headerEntity).ExecuteCommand();
                }

                if (!logDb.Queryable<THeader>().WhereClassByPrimaryKey(headerEntity).Any())
                {
                    logDb.Insertable(headerEntity).ExecuteCommand();
                }
                
                //_dbClient.AsTenant().CommitTran();  // <----------------------------------------------------------- 4
                logDb.CommitTran();
                db.CommitTran();
            }
            catch (SqlSugarException dbe)
            {
                //_dbClient.AsTenant().RollbackTran();
                logDb.RollbackTran();
                db.RollbackTran();

                _logger.LogError("在导入数据时发生数据库异常:{}。", dbe.Message);
            }
            catch (Exception)
            {
                //_dbClient.AsTenant().RollbackTran();
                logDb.RollbackTran();
                db.RollbackTran();
                throw;
            }
        }
    }
    catch (Exception e)
    {
        _logger.LogError("在导入数据时发生其它异常:{}。", e.Message);
    }
    
    ...
}


热忱回答4