You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求助:System.IndexOutOfRangeException在List.Add中莫名抛出的原因排查

异常排查:未调用List.Add()却抛出IndexOutOfRangeException

问题背景

简化后的异常堆栈跟踪:

System.IndexOutOfRangeException: Index was outside the bounds of the array.
at System.Collections.Generic.List1.Add(T item) at PPM.Dal.Entities.Code.SqlHelper.ExecuteEntityArray[TEntity](CommandType commandType, String commandText, String connectionString, Nullable1 commandTimeout, DynamicParameters parameters, Boolean useTransaction)

对应的ExecuteEntityArray方法代码:

private static TEntity[] ExecuteEntityArray<TEntity>(CommandType commandType, string commandText, string connectionString, int? commandTimeout, DynamicParameters parameters, bool useTransaction) where TEntity : class, new()
{
    var sqlAction = StartLog(commandType, commandText, null, parameters);

    try
    {
        TEntity[] result;

        var transaction = CurrentTransaction;
        if (useTransaction && transaction != null && (connectionString == null || transaction.ConnectionString == connectionString))
        {
            // Use the existing transaction to execute the query
            result = transaction.SqlConnection.Query<TEntity>(sql: commandText, param: parameters, transaction: transaction.SqlTransaction, commandType: commandType, commandTimeout: commandTimeout).ToArray();
        }
        else
        {
            if (connectionString == null)
            {
                connectionString = ConnectionStringData;
            }

            using (var sqlConnection = new SqlConnection(connectionString))
            {
                result = sqlConnection.Query<TEntity>(sql: commandText, param: parameters, commandType: commandType, commandTimeout: commandTimeout).ToArray();
            }
        }

        EndLog(sqlAction, null);
        return result;
    }
    catch (SqlException ex)
    {
        EndLog(sqlAction, ex);
        HandleSqlExceptions(ex, null);
        throw;
    }
    catch (Exception ex)
    {
        EndLog(sqlAction, ex);
        throw;
    }
}

困惑点:方法中并未直接调用List.Add(),但堆栈明确指向该方法内抛出此异常;确认使用无参数throw保留了原始堆栈,排除堆栈错误的可能。

补充:该问题仅在生产服务器偶发,本地难以复现,但已找到生产环境复现方式。

可能的原因分析

  • Dapper内部实现调用:Query<TEntity>方法底层会用List<TEntity>存储查询结果,最终通过ToArray()转换为数组。堆栈中的List.Add()是Dapper内部执行时触发的,并非你的代码直接调用。
  • 实体类(TEntity)存在不安全并发操作:如果TEntity的无参构造函数或属性setter中,有操作静态List的逻辑,生产环境高并发场景下,多个线程同时修改这个静态List就会触发IndexOutOfRangeException。此时异常会在Dapper实例化实体、赋值属性的过程中抛出,堆栈会显示为List.Add()被你的ExecuteEntityArray方法调用。
  • Dapper版本存在并发bug:旧版本的Dapper在处理查询结果映射时,若存在并发修改内部缓存(比如实体映射信息)的情况,可能导致内部List操作异常。
  • 查询结果与实体映射冲突:如果查询返回的列存在重复名称、或者实体属性的映射逻辑有异常,可能导致Dapper在填充实体时触发意外的集合操作,进而引发异常。

排查建议

  1. 检查TEntity的无参构造函数和所有属性的setter方法,确认是否有操作静态集合的代码,若有则替换为线程安全集合(比如ConcurrentBag)或添加锁控制。
  2. 升级Dapper到最新稳定版本,验证是否是旧版本的已知bug导致。
  3. 在生产复现场景中,捕获更详细的异常上下文(比如当前执行的SQL语句、参数值、对应的TEntity类型),缩小排查范围。

内容的提问来源于stack exchange,提问作者Borislav-K

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 17:42:43