#c# #linq #deferred-execution
#c# #linq #отложенное выполнение
Вопрос:
Запрос Linq не выполняется до тех пор, пока последовательность, возвращаемая запросом, фактически не будет повторена.
У меня есть запрос, который используется неоднократно, поэтому я собираюсь инкапсулировать его внутри метода. Я хотел бы знать, мешает ли это отложенному выполнению.
Если я инкапсулирую запрос Linq в метод, подобный приведенному ниже, запрос выполняется в строке 2, а не в строке 1, где вызывается метод. Правильно ли это?
public IEnumerable<Person> GetOldPeopleQuery()
{
return personList.Where(p => p.Age > 60);
}
public void SomeOtherMethod()
{
var getWomenQuery = GetOldPeopleQuery().Where(p => p.Gender == "F"); //line 1
int numberOfOldWomen = getWomanQuery.Count(); //line 2
}
P.S. Я использую Linq-To-EF, если это имеет какое-либо значение.
Ответ №1:
Запрос вычисляется с задержкой при первом перечислении результата, на который не влияет помещение его внутрь метода.
Однако в вашем коде есть еще одна вещь, которая будет очень неэффективной. Как только вы вернете IEnumerable
, следующим оператором linq, применяемым к коллекции, будет запрос linq-to-objects. Это означает, что в вашем случае вы будете загружать всех пожилых людей из базы данных, а затем отфильтровывать женщин в памяти. То же самое с подсчетом, это будет сделано в памяти.
Если вы вместо этого вернете IQueryable<Person>
, эти два вопроса будут оценены с использованием linq-to-entities, а фильтрация и суммирование могут быть выполнены в базе данных.
Комментарии:
1. В этом вопросе нет указаний на то, что на самом деле задействована база данных. Но если это так, я согласен с вами о неэффективности.
2. Спасибо! поэтому я буду использовать IQueryable<T> вместо этого.