2017-02-20 18 views
1

У меня проблема, когда при выполнении цикла по моему оператору foreach мое приложение возвращает ошибку тайм-аута. Обратите внимание: я не могу изменить или сделать представление в таблице, которую я запрашиваю.Неэффективное заявление о начале работы LINQ

IEnumerable<MyTable> TContextData; 
if (!string.IsNullOrEmpty(id) 
    || !string.IsNullOrEmpty(name) 
    || !string.IsNullOrEmpty(cell) 
    ) 
{ 
    TContextData = (from e in db.mytable 
        where (!String.IsNullOrEmpty(e.id)) 
        select e); 
} 
else 
{ 
    TContextData = null; 
} 

List<EachC> mDatalist = new List<EachC>(); 

if (TContextData != null) 
{ 
    foreach (var i in TContextData.ToList()) 
    { 
     EachMR EachM = new EachMR(); 

     EachM.Feature = i.TRuid; 
     EachM.Feature2 = i.TRuid2; 
     EachM.Feature3 = i.TRuid3; 
     EachM.Date = GetInnerTextfromXML(EachM.Feature3, "/Sections/Multiple/Functions/Group/Date"); 
     mdatalist.Add(EachM); 
    } 
} 

Существует около 40 тыс. Строк для повторения. Есть ли способ сделать это более эффективным?

Сообщение об ошибке: исключение типа «System.OutOfMemoryException» произошло в System.Data.Entity.dll, но не был обработан в пользовательском коде

я увеличила время ожидания в контексте с

((IObjectContextAdapter)this).ObjectContext.CommandTimeout = 0; 

, но безрезультатно, поскольку это просто проблема маскировки.

+3

Вам нужно все содержимое строки 'mytable'? Действительно ли на каждую строку действительно нужно воздействовать «делать вещи»? Может ли 'e.id' когда-либо быть нулевым или просто пустым или ему действительно нужны обе проверки? Разве это не так, если вы перед вызовом «.ToList()» второй запрос? Вам нужно сохранить изменения обратно в базу данных? Получаете ли вы доступ к дочерним таблицам 'mytable' в« do stuff »(смотрите ли запросы, выполняемые лениво в цикле' for')? Профилировали ли вы это, чтобы увидеть, что работает SQL? Скорее всего, вы делаете 40 000 запросов вместо 1. –

+0

Почему '.Take (1)' предотвратит тайм-ауты в вашем 'foreach'? - Я имею в виду, очевидно, что он вернет только одну строку, но почему бы вам получить одну строку вместо пустой (или нулевой) проверки? – gobes

+0

Как ваше приложение размещено, сколько времени занимает время? Кроме того, ваша проблема может быть не с изображением linq, которое вы указали, но с элементом '#Do Stuff', который вы нам не показали. Вам нужно прокомментировать свой код, особенно часть #Do Stuff, и посмотреть, какая часть занимает слишком много времени. –

ответ

-1

Без точного сообщения сложно сказать, откуда наступает тайм-аут; но я думаю, это не тайм-аут SQL.

В действительности ваш код выполняет запрос к базе данных для каждой строки, которую вы пытаетесь получить в своем foreach. Я имею в виду, что вы, вероятно, выполняете 40 000 запросов. Вместо этого вы должны загрузить свои данные в память и выполнить свой код в списке с помощью метода .ToList(), который выполнит запрос один раз.

IEnumerable TContextData; 

if (!string.IsNullOrEmpty(id) 
|| !string.IsNullOrEmpty(name) 
|| !string.IsNullOrEmpty(cell)) 
{ 
    TContextData = (from e in db.mytable where (!string.IsNullOrEmpty(e.id)) select e); 
} 

foreach(var i in TContextData.ToList()) 
{  
    //do stuff 
} 

Опять же, я говорю, не имея всего контекста; ответ будет немного отличаться, если вы используете EF, LinqToSQL, или DataReader превращали в IEnumerable ...

+0

Это неправда - если он не использует 'TContextData' где-либо еще внутри цикла, этот вызов создает один« IEnumerator »и не будет выполняться 40000 раз. – decPL

+0

Спасибо Горы. Я пробовал это, но это ошибка, которую я получаю: {«Было исключено исключение типа« System.OutOfMemoryException ».} – AMorrisey

+0

@decPL Я согласен, что' IEnumerator' будет создан только один раз, и запрос будет выполнен только когда код перечислит его, но в чем же разница между перечислением на «Enumerator» и перечислением в «List », если не отложенное выполнение? Я всегда, хотя EF запрашивал базу данных для каждой отдельной строки (с маской дерева запросов); У меня были некоторые проблемы с этим поведением, и использование «ToList» резко сократило количество запросов ... может быть, из-за навигации свойств? – gobes

0

Удаление .ToList() может помочь. Ваш код излишне буферизует все, что возвращает запрос в списке, а затем повторяет этот список. Просто переверните TContextData.

 Смежные вопросы

  • Нет связанных вопросов^_^