1

Этот вопрос несколько связан с my previous one ответ на который помог мне найти причину, почему этот простой итерации через SqlDataReader:.SqlDataReader.ReadColumnHeader NullReferenceException

m_aFullIDList = New Generic.List(Of Integer) 

While i_oDataReader.Read 
    m_aFullIDList.Add(i_oDataReader.GetInt32(0)) 
End While 

m_iTotalNumberOfRecords = m_aFullIDList.Count 

не возвращает все записи. Выявлено, когда Generic.List изменяет свою Capacity, чтобы разместить больше элементов (например, от 2^19 до следующего 2^20), в этот момент простые QuqDataReader Quits, его метод Read возвращает False, как будто записей больше нет.

Большую часть времени, когда он тихо уходит, никакого исключения не выбрасывается. Но каждый сейчас и потом я получаю:

NullReferenceException { «Ссылка на объект не указывает на экземпляр объекта .»}

в System.Data.SqlClient.SqlDataReader.ReadColumnHeader (Int32 я)
на System.Data.SqlClient.SqlDataReader.ReadColumn (Int32, Boolean я SetTimeout) в System.Data.SqlClient.SqlDataReader.GetInt32 (Int32 I)

Я знаю, за то, что все записи возвращенного по хранимой процедуре, используемой Re ader (это один столбец) являются целыми значениями. Если я удаляю строку m_aFullIDList.Add и вместо этого просто прочитаю значение в целочисленную переменную ИЛИ, если я предварительно выделил емкость универсального списка знанию большого числа - эта проблема не возникает. По-видимому, это происходит только тогда, когда List перераспределяет Capacity - это влияет на читателя.

Я также попытался использовать другие структуры (ArrayList, даже Array, используя Array.Resize), как только емкость этой структуры перераспределяется за определенную точку - это разрывает SqlDataReader.

Этот проект ASP.NET является довольно сложным, поэтому, когда я попытался воссоздать проблему в автономном простом проекте, состоящем только в том, чтобы выполнять чтение и чтение в List - проблема не возникает. Любая идея, что происходит и как это можно исправить?

+1

Я уверен, что вы испытываете один из двух симптомов: в домене приложения нет памяти ** или ** читатель набирает свой тайм-аут. –

+0

@neoistheone благодарит за быстрый ответ. Я подумал об этом, но оба таймаута соединения и команды установлены на значение lager, чем требуется для выполнения SP (не хватает ли каких-либо других тайм-аутов?), и у меня, похоже, тоже много памяти (также предваряется предварительное распределение Capacity) –

ответ

0

Я думаю, что, наконец, понял.

Логика в моем коде было 2 шагов - вызов функции, которая возвращает SqlDataReader, а затем использовать этот считыватель в другой функции для заполнения списка:

Dim oReader as SqlDataReader = GetTheReader() 

FillTheList(oReader) 

Функция GetTheReader() выглядел примерно так:

Function GetTheReader() as SqlDataReader 
    Dim oConn As New SqlConnection("Connection String") : oConn.Open() 
    Dim oComm As New SqlCommand("Stored Procedure", oConn) 

    Dim oReader As SqlDataReader = oComm.ExecuteReader(CommandBehavior.CloseConnection) 

    Return oReader 
End Function 

Это открытое соединение как local переменная, которая вышла из сферы действия, когда функция вернулась обратно к вызывающей программе. И когда был заполнен Generic List, после другого выделения ресурсов Garbage Collection заявила, что память уничтожила устаревшие переменные (и закрыла это соединение). Я остался с SqlDataReader без действительного соединения.

Мое текущее решение - создать соединение вне функции GetTheReader и передать его в качестве одного из параметров.