2016-01-19 2 views
-2

части коды я работаю получаетПеребор Linq-на-Сущность IEnumerable причины OutOfMemoryException

IEnumerable<T> items 

, где каждый элемент содержит класс со свойствами, отражающих таблицу базы данных MSSQL.

Таблица базы данных имеет общее количество 953664 строк. Набор данных в коде отфильтрован до набора из 284360 строк.

Следующий код генерирует исключение OutOfMemoryException, когда процесс достигает примерно 1,5 ГБ памяти.

private static void Save<T>(IEnumerable<T> items, IList<IDataWriter> dataWriters, IEnumerable<PropertyColumn> columns) where T : MyTableClass 
    { 
     foreach (var item in items) 
     { 
     } 
    } 

Переменная элементы имеет тип

IQueryable<MyTableClass> 

Я не могу найти кого-нибудь с такой же установкой, и друга решения, которые я нашел здесь не действует.

Я также пробовал пейджинг, используя Skip и Take с размером страницы 500, но это занимает много времени и заканчивается тем же результатом. Кажется, что объекты не выпускаются после каждой итерации. Как так?

Как я могу переписать этот код, чтобы справиться с большим набором коллекций?

+0

Вы должны * абсолютно * разбивать страницы на страницы, если у вас есть много элементов для работы. Мы не могли бы рассказать вам, как вы все еще держите ссылки на объект в * коде, который вы даже не указали *. – Servy

+0

@Servy Что именно вам не хватает? Переменная элементов - это IQueryable, так что, например, items.count() поместит весь запрос в память. – smarty

+0

Если вы разбиваете на страницы, это не будет, нет. Вы должны иметь возможность предоставить пример, способный реплицировать проблему, при которой вы разбиваете запрос на запрос и показываете, что элементы не будут исправлены после того, как вы закончили с данной страницей. – Servy

ответ

0

Ну, как Servy уже сказал, что вы не предоставили свой код, так что я постараюсь сделать некоторые прогнозы ... (Извините за мой английский)

Если у вас есть исключение в «Еогеасп (вар элемент в элементах) «когда вы используете пейджинг, тогда, я думаю, что-то не так с пейджингом. Я написал несколько примеров, чтобы объяснить мою идею.

Если в первом примере я предлагаю вам (просто для проверки) включить фильтр в функцию сохранения.

private static void Save<T>(IQueryable<T> items, IList<IDataWriter> dataWriters, IEnumerable<PropertyColumn> columns) where T : MyTableClass 
{ 
    int pageSize = 500; //Only 500 records will be loaded. 
    int currentStep = 0; 
    while (true) 
    { 
     //Here we create a new request into the database using our filter.     
     var tempList = items.Where(yourFilter).Skip(currentStep * pageSize).Take(pageSize); 
     foreach (var item in tempList) 
     { 
      //If you have an exception here maybe something wrong in your dataWriters or columns. 
     } 
     currentStep++; 
     if (tempList.Count() == 0) //No records have been loaded so we can leave. 
      break; 
    } 
} 

Второй пример показывает, как использовать подкачку без каких-либо изменений в функции Save

int pageSize = 500; 
int currentStep = 0; 
while (true) 
{ 
    //Here we create a new request into the database using our filter.     
    var tempList = items.Where(yourFilter).Skip(currentStep * pageSize).Take(pageSize); 
    Save(tempList, dataWriters, columns); //Calling saving function. 
    currentStep++; 
    if (tempList.Count() == 0) 
     break; 
} 

Попробуйте оба, и вы будете либо решить проблему или найти другое место, где поднимается исключение ,

Кстати, еще одно потенциальное место - ваши данные. Я предполагаю, что вы храните все данные, которые были получены из базы данных. Может быть, вы не должны сохранять все данные? Просто вычислите размер памяти, чтобы все объекты были необходимы.

P.S. И не используйте while (true) в вашем коде. Это просто пример :)

+0

Спасибо за предоставление примеров. Что касается кода поискового вызова, мой код такой же, как ваш, хотя я не добавил сюда фильтры.Я узнал, что EF хранит данные в памяти для отслеживания изменений, и поскольку в настоящее время мы используем .NET 3.5, у нас нет возможности отключить отслеживание с помощью AsNoTracking(). – smarty