#c# #.net #linq #c#-4.0
#c# #.net #linq #c #-4.0
Вопрос:
У меня есть запрос LINQ, такой как:
using(csv.......)
{
csv.Select(x => new Data() { ID = x[27], Raw = String.Join(",", x) });
}
//Do some stuff
//Now I want to use the result of the query
foreach(var item in ??)
{
}
Запрос возвращает IEnumerable в моей using
инструкции, но как мне объявить, а затем назначить переменную, чтобы я мог использовать ее позже в foreach
инструкции?
Комментарии:
1. Я предполагаю, что запрос больше не работает после удаления MyObject. Это верно?
2. Похоже, в этом и заключается проблема. О, ладонь в ладонь! ОГО! ОГО! ОГО!
Ответ №1:
Вы должны хорошо воспользоваться IEnumerable
. Прелесть этого в том, что ваш запрос не оценивается до тех пор, пока вы не понадобитесь. Как только вы выполните ToList()
, ваш запрос будет выполнен полностью. Рекомендуется использовать IEnumerable
как можно больше.
Вы просто можете определить IEnumerable<Data>
во внешней области следующим образом
IEnumerable<Data> myDataList;
using(myObject.......)
{
myDataList =csv.Select(x => new Data() { ID = x[27], Raw = String.Join(",", x) });
}
// do your stuffs
// and just use the IEnumerable<Data> in your foreach loop
foreach(var item in myDataList)
{
// here item is typeof(Data)
}
Ответ №2:
Тип запроса — это тот, IEnumerable<Data>
который вы можете объявить вне using
блока. Однако из комментариев очевидно, что вы не можете перечислять после того, как myObject
она была удалена. Если вы не хотите извлекать все элементы в список перед выходом из using
блока, ваш единственный вариант — выполнить перечисление внутри using
блока. Для извлечения данных из базы данных требуется открытое соединение с этой базой данных и т.д.
using(myObject.......)
{
var query = csv.Select(x => new Data() { ID = x[27], Raw = String.Join(",", x) });
//Do some stuff
//Now I want to use the result of the query
foreach (var item in query)
...
}
Комментарии:
1. Изначально я пробовал это до того, как спросил, но в переменной ничего не было
2. Я думаю, вам нужно сделать . ToList() для выполнения запроса.
3. @Jon: Когда вы говорите, что в переменной ничего нет, вы имеете в виду, что это null или что это просто пустое значение IEnumerable?
4. @TerryDonaghe: Нет, выполнение
foreach
приведет к отложенному выполнению запроса и будет иметь преимущество в том, что не будет извлекать все данные в память сразу. Поскольку Джон говорит, что у него в коллекции от шести до восьми миллионов элементов, использование ToList привело бы к значительному и ненужному снижению производительности.
Ответ №3:
Объявить переменную вне блока using.
Вызовите ToList()
или ToArray()
для выполнения запроса.
List<Data> data=null;
using(myObject.......)
{
data=csv.Select(x => new Data() { ID = x[27], Raw = String.Join(",", x) }).ToList();
}
Если возможно выполнить запрос после возврата из using
предложения, вы могли бы сделать:
IEnumerable<Data> data=null;
using(myObject.......)
{
data=csv.Select(x => new Data() { ID = x[27], Raw = String.Join(",", x) });
}
Но если это так, почему вы вообще помещаете ее в using
предложение?
Если запрос зависит от того, myObject
что он не удален, у вас есть два варианта:
- Используйте
ToList()
для немедленного выполнения запроса и загрузки всего этого в память. - утилизировать
myObject
позже.
Комментарии:
1. Имеет ли вызов ToList() такое же снижение производительности, как и foreach? Причина, по которой я спрашиваю, заключается в том, что в IEnumerable<T> содержится 6-8 миллионов элементов
2. Список загрузит все элементы в память.
3. Но foreach не будет? У меня не может быть так много памяти!