Я получаю странную проблему, когда я могу вернуть результаты вызова из хранимой процедуры, но код ретроспективно терпит неудачу.Свойство SqlDataReader's Connection Null
public IEnumerable<T> ExecuteStoredProcedure<T>(string storedProcedureName, IDataMapper<T> mapper, IDictionary<string, object> parameters)
{
using (var connection = new SqlConnection(connectionString))
{
using (var cmd = new SqlCommand(storedProcedureName, connection))
{
cmd.CommandType = CommandType.StoredProcedure;
foreach (var key in parameters.Keys)
{
cmd.Parameters.AddWithValue(key, parameters[key]);
}
connection.Open();
SqlDataReader reader = cmd.ExecuteReader();
//return MapRecordsToDTOs(reader, mapper);
//let's test:
IEnumerable<T> result = MapRecordsToDTOs(reader, mapper);
var x = (new List<T>(result)).Count;
System.Diagnostics.Debug.WriteLine(x);
return result;
}
}
}
private static IEnumerable<T> MapRecordsToDTOs<T>(SqlDataReader reader, IDataMapper<T> mapper)
{
if (reader.HasRows)
{
while (reader.Read())
{
System.Diagnostics.Debug.WriteLine(reader["Id"]); //what's going on...
yield return mapper.MapToDto((IDataRecord)reader);
}
}
}
Вызов этого кода показывает, что переменная x
всегда представляет количество строк, я бы ожидать от вызова моих хранимых процедур.
Кроме того, мой вывод отладки показывает идентификационные значения, которые я ожидаю увидеть.
Однако после получения этих результатов я получаю сообщение об ошибке An exception of type 'System.InvalidOperationException' occurred in System.Data.dll but was not handled in user code
из строки if (reader.HasRows)
(т. Е. Уже выполненной). Браузер, из которого я вызываю этот запрос, показывает HTTP Error 502.3 - Bad Gateway
.
Я подозреваю, что причина заключается в системы расчета ID
и X
значения для отладки отдельно, как это будет вернуть реальный выход пользователя. Таким образом, он выполняет ленивую операцию для получения значений IEnumerable в момент, когда он должен их возвращать; только к этой точке операторы using
вызвали вызовы методов dispose, и поэтому соединение читателя является нулевым (это то, что я вижу, когда проверяю свойства переменной reader
во время отладки).
Кто-нибудь видел подобное поведение раньше/это ошибка; или я просто пропустил что-то очевидное?
Дополнительный код:
public interface IDataMapper<T>
{
T MapToDto(IDataRecord record);
}
public class CurrencyMapper: IDataMapper<CurrencyDTO>
{
const string FieldNameCode = "Code";
const string FieldNameId = "Id";
const string FieldNameName = "Name";
const string FieldNameNum = "Num";
const string FieldNameE = "E";
const string FieldNameSymbol = "Symbol";
public CurrencyMapper() { }
public CurrencyDTO MapToDto(IDataRecord record)
{
var code = record[FieldNameCode] as string;
var id = record[FieldNameId] as Guid?;
var name = record[FieldNameName] as string;
var num = record[FieldNameNum] as string;
var e = record[FieldNameE] as int?;
var symbol = record[FieldNameSymbol] as char?;
return new CurrencyDTO(id, code, num, e, name, symbol);
}
}
public class CurrencyRepository
{
const string SPReadAll = "usp_CRUD_Currency_ReadAll";
readonly SqlDatabase db;
public CurrencyRepository()
{
db = new SqlDatabase(); //stick to SQL only for the moment for simplicity
}
public IEnumerable<CurrencyDTO> GetCurrencyCodes()
{
var mapper = new CurrencyMapper();
return db.ExecuteStoredProcedure(SPReadAll, mapper);
}
}
public class CurrencyDTO
{
readonly Guid? id;
readonly string code;
readonly string num;
readonly int? e;
readonly string name;
readonly char? symbol;
public CurrencyDTO(Guid? id,string code,string num,int? e,string name, char? symbol)
{
this.id = id;
this.code = code;
this.num = num;
this.e = e;
this.name = name;
this.symbol = symbol;
}
public Guid? Id { get { return id; } }
public string Code { get { return code; } }
public string Num { get { return num; } }
public int? E { get { return e; } }
public string Name { get { return name; } }
public char? Symbol { get { return symbol; } }
}
вы пытались осмотреть (или использовать в своем коде) 'reader.HasRows' только после того, как' SqlDataReader читателя = cmd.ExecuteReader() ; 'и раньше, чтобы вызвать« MapRecordsToDTOs »? – McNets
вы можете попробовать: 'reader = await cmd.ExecuteReaderAsync();' – McNets
@mcNets: Функция 'MapRecordsToDTO' подтверждает это' читателя.HasRows' истинно, так как он может перебирать эти строки, чтобы позволить 'x' получить правильное значение, а для' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' 'правильно' '. заявления. – JohnLBevan