Я знаю, что этот ответ слишком поздно, чтобы помочь оригинальному постеру, но я надеюсь, что он может помочь другим, кто столкнулся с подобной проблемой.
Во-первых, это DataTable
, который являетсяпроблема не в DataAdapter
.
Проблема может заключаться в том, что у вас действительно недостаточно памяти (в этом случае мой ответ не поможет).Вы можете сделать математику, чтобы выяснить, может ли это быть так - количество записей x приблизительное число байтов на запись.Если это приближается к 2 ГБ на 32-битной платформе или вашей доступной оперативной памяти на 64-битной платформе, тогда единственный вариант - уменьшить количество записей, количество полей или придумать подход, который использует DataReader вместо DataTable.
В вашем случае у вас есть 150 КБ записей, давайте предположим, что для каждой из них требуется 1 КБ памяти, что дает нам округлую цифру 150 МБ.Даже на 32-битной машине с 2 ГБ оперативной памяти это должно быть хорошо (при условии, что не происходит много подобного выделения памяти).В вашем случае у вас есть 64-битная машина с 128 ГБ ОЗУ (приятно).Логично, что вы не должны получать ошибки памяти.
Так в чем же причина проблемы?Это Куча Больших Объектов (LOH).Зачем?DataTable
создает массив для хранения этих записей.Насколько я понимаю, он создает массив из 50, а затем увеличивается по мере добавления записей.Любое выделение памяти более 85 000 байт будет происходить из кучи больших объектов.(Вы работали на 64-битной платформе, так что получается, что как только вы достигнете 10 625 записей, выделения начнут поступать из кучи больших объектов.) Проблема с кучей больших объектов заключается в том, что она не уплотняется.Так что может быть много свободного места, но нет ни одного непрерывного блока, который достаточно велик.С .net 4.5 Microsoft улучшила его с точки зрения объединения смежных фрагментов, но не реорганизует их для создания больших блоков свободного пространства.В результате я получаю исключение «Недостаточно памяти». Как только вы заблуждаетесь в LOH, мой вопрос - только вопрос времени.
Решение?
установить начальную емкость DataTable
.При извлечении записей из базы данных это будет означать сначала подсчет, так что это будет происходить за счет дополнительного запроса к базе данных, а затем:
.
.
dsGrid.InitialCapacity = count;
daGrid.Fill(dsGrid, "Query");
.
.
Хотя это не позволяет избежать отклонения от LOH, онодолжно означать, что он делает только одно распределение вместо нескольких.Таким образом, помимо исключения исключения из нехватки памяти, вы также должны получить выигрыш в производительности (компенсируемый необходимостью дополнительного запроса к базе данных).
Вы можете сделать сборщик мусора .net компактной кучей больших объектов, ноВы можете только сказать, чтобы сделать это в следующий раз, когда он работает.Я склонен использовать это, если я знаю, что заблудился в куче больших объектов.Это может быть излишним, но рассмотрите возможность внесения поправок в мое предложение:
.
.
dsGrid.InitialCapacity = count;
if (count > 10625)
{
System.Runtime.GCSettings.LargeObjectHeapCompactionMode =
System.Runtime.GCLargeObjectHeapCompactionMode.CompactOnce;
}
daGrid.Fill(dsGrid, "Query");
.
.