Я изо всех сил пытался выяснить причину исключения с помощью следующей трассировки стека (намеренно сокращенной):
System.IndexOutOfRangeException: индекс вышел за пределы массива. в System.Collections.Generic.List1.Add(T item) в PPM.Dal.Entities.Code.SqlHelper.ExecuteEntityArray[TEntity](CommandType CommandType, String CommandText, String ConnectionString, Nullable1 CommandTimeout, параметры DynamicParameters, логическое значение useTransaction)
Метод PPM.Dal.Entities.Code.SqlHelper.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 ex. Здесь у нас есть голый «выброс», который должен поддерживать исходную трассировку стека исключения.
Кто-нибудь знает, как этот метод может вызвать это исключение?
P.S.: Я не знаю, имеет ли это какое-либо очевидное значение, но проблема возникает довольно редко и только на наших рабочих серверах, поэтому ее довольно сложно воспроизвести локально. Мне пока не удалось, но у меня есть способ воспроизвести это на рабочем сервере.
Такое ощущение, что здесь не хватает какой-то трассировки стека — я предполагаю, что это происходит из-за каких-то внутренних компонентов Query<T>() или ToArray().
Пробовали ли вы зарегистрировать исключение и получить ПОЛНУЮ трассировку стека? Я думаю, что что-то происходит внутри Query, или Query возвращает что-то, с чем ToArray не может работать. Хотя напиши мне, когда сделаешь





Я наконец понял это. Оказывается, проблема была в EndLog(). По какой-то причине он был пропущен в трассировке стека. Возможно, когда сборка Release завершена, функция EndLog() была встроена по какой-то причине (я до сих пор не понимаю, почему). Но был список, к которому обращались сразу 2 потока. Я добавил блокировку к операции добавления, и это устранило проблему.
Спасибо за все ответы!
Может быть, что-то вроде многопоточного параллелизма? Возможно,
CurrentTransactionодновременно используется из разных потоков.