请教单例模式IOC的单元测试 返回

SqlSugar 沟通中
7 590

我是按照官方的推荐方式进行注册的

 public static void RegisterSqlSugar(ServiceCollection serviceCollection)
 {
     serviceCollection.AddSingleton<ISqlSugarClient>(p =>
     {

         var mySqlSetting = new MySqlSetting(config);

         var db = new SqlSugarScope(new ConnectionConfig()
         {
             ConnectionString = mySqlSetting.Value.MySqlConnection, // 替换为你的连接字符串
             DbType = DbType.MySql,                     // 数据库类型
             IsAutoCloseConnection = true,              // 自动释放数据库
             InitKeyType = InitKeyType.Attribute,        // 从实体特性读取主键信息
             ConfigureExternalServices = new ConfigureExternalServices
             {
                 DataInfoCacheService = new SugarCache(), //擴展二級緩存
                 SqlFuncServices = SqlFuncMySql.MySqlFuncExternal(), // 擴展自定義sql方法
             },
             MoreSettings = new ConnMoreSettings
             {
                 IsAutoRemoveDataCache = true,
                 DefaultCacheDurationInSeconds = 60 * 10,//默认缓存时间为 10 分钟
                 DisableMillisecond = true //插入和更新禁用毫秒
             },
         });
         return db;
     });
 }

为了保证万无一失 , 我写了一个这样子的单元测试

private readonly ISqlSugarClient _db;

public SqlSugarConcurrentTest()
{
    _db = GetInterface<ISqlSugarClient>();
}

[Fact]
public async Task Should_Handle_Concurrent_Insert_Correctly()
{
    // Arrange
    var baseId = Guid.NewGuid().ToString();
    var tasks = new List<Task<int>>();
    
    // Act
    for (int i = 0; i < 10; i++)
    {
        var testData = new RolesStaffMappingTable
        {
            Id = $"{baseId}-{i}".Right(36),
            RoleId = Guid.NewGuid().ToString(),
            StaffId = Guid.NewGuid().ToString(),
            IsDeleted = false
        };
        
        tasks.Add(_db.Insertable(testData).ExecuteCommandAsync());
    }

    var results = await Task.WhenAll(tasks);
    
    // Assert
    results.All(r => r == 1).ShouldBeTrue();
    
    var count = await _db.Queryable<RolesStaffMappingTable>()
        .Where(x => x.Id.StartsWith(baseId))
        .CountAsync();
        
    count.ShouldBe(10);
}

但是运行到了

 var results = await Task.WhenAll(tasks);

就会报以下错误

SqlSugar.SqlSugarException
Cannot Open when State is Connecting.
   at SqlSugar.MySqlProvider.ExecuteCommandAsync(String sql, SugarParameter[] parameters)
   at SqlSugar.MySqlProvider.ExecuteCommandAsync(String sql, SugarParameter[] parameters)
   at SqlSugar.InsertableProvider`1.ExecuteCommandAsync()
   at BTypeWheelsetBoltManagement.IntegrationTests.SqlSugarConcurrentTest.Should_Handle_Concurrent_Insert_Correctly() in 
   F:\Aaron项目\GJCX24001\BTypeWheelsetBoltManagement\BTypeWheelsetBoltManagement.IntegrationTests\SqlSugarConcurrentTest.cs:line 39
   at Xunit.Sdk.TestInvoker`1.<>c__DisplayClass48_0.<<InvokeTestMethodAsync>b__1>d.MoveNext() in /_/src/xunit.execution/Sdk/Frameworks/Runners/TestInvoker.cs:line 276
--- End of stack trace from previous location ---
   at Xunit.Sdk.ExecutionTimer.AggregateAsync(Func`1 asyncAction) in /_/src/xunit.execution/Sdk/Frameworks/ExecutionTimer.cs:line 48
   at Xunit.Sdk.ExceptionAggregator.RunAsync(Func`1 code) in /_/src/xunit.core/Sdk/ExceptionAggregator.cs:line 90

请问是测试用例有问题 , 还是注册方式有问题?






热忱回答7

  • image.png

    0 回复
  • @fate sta:你这个文档写在哪里 ? 我又翻了一遍  ,没有找到 . 

    0 回复
  • ?? ?? VIP0
    1周前

    @Aaron 傲: 一看你就没仔细看

    0 回复
  • @fate sta:我换成了SqlSugarClient 模式 , 但是还是出现Cannot Open when State is Connecting.

    以下是注册代码

     public static void RegisterSqlSugar(this ServiceCollection serviceCollection)
     {
         serviceCollection.AddScoped<ISqlSugarClient>(p =>
         {
             var db = new SqlSugarClient(new ConnectionConfig()
             {
                 ConnectionString = mySqlSetting.Value.MySqlConnection, // 替换为你的连接字符串
                 DbType = DbType.MySql, // 数据库类型
                 IsAutoCloseConnection = true, // 自动释放数据库
                 InitKeyType = InitKeyType.Attribute, // 从实体特性读取主键信息
                 ConfigureExternalServices = new ConfigureExternalServices
                 {
                     DataInfoCacheService = new SugarCache(), //擴展二級緩存
                     SqlFuncServices = SqlFuncMySql.MySqlFuncExternal(), // 擴展自定義sql方法
                 },
                 MoreSettings = new ConnMoreSettings
                 {
                     IsAutoRemoveDataCache = true,
                     DefaultCacheDurationInSeconds = 60 * 10, //默认缓存时间为 10 分钟
                     DisableMillisecond = true //插入和更新禁用毫秒
                 },
             });
             return db;
         });
     }

    以下为测试用例

     private readonly ISqlSugarClient _db;
    
     public SqlSugarConcurrentTest()
     {
         _db = GetInterface<ISqlSugarClient>();
     }
    
     [Fact]
     public async Task Should_Handle_Concurrent_Insert_Correctly()
     {
         // Arrange
         var tasks = new List<Task<int>>();
         var addList = new List<RolesStaffMappingTable>();
    
         // Act
         for (int i = 0; i < 10; i++)
         {
             var testData = new RolesStaffMappingTable
             {
                 Id = IdHelper.NewGuid7(),
                 RoleId = IdHelper.NewGuid7(),
                 StaffId = IdHelper.NewGuid7(),
                 IsDeleted = false
             };
             addList.Add(testData);
             tasks.Add(_db.Insertable(testData).ExecuteCommandAsync());
         }
    
         var results = await Task.WhenAll(tasks);
    
         // Assert
         var idList = addList.Select(p => p.Id).ToList();
    
         var sqlList = await _db.Queryable<RolesStaffMappingTable>()
             .Where(x => idList.Contains(x.Id))
             .ToListAsync();
    
         foreach (var item in addList)
         {
             sqlList.Any(p => p.Id == item.Id).ShouldBeTrue();
         }
     }

    image.png


    2025-7-4 10:00

    没事了已经了解了 , 也是简单粗暴 , 直接 newCopy  , 这种属于代码内的并发需要额外处理 , 给不同的线程分配不同的ORM对象 . 

    实际上用户的请求并行 , 每请求一次 , 就是一个对象 , 只要是方法本身是异步就行了 , 无需额外的 newCopy




    0 回复
  • @??: 的确是没认真 , 那个 Scope 和 Client , 不仔细看还真看不出来 . 

    0 回复
  • image.png

    0 回复
  • hhh

    我一直有个疑惑,SqlSugarClient 和SqlSugarScope 似乎名字应该换一下。

    0 回复