У меня проблемы с пониманием IQueryable <T>
Итак, я пытаюсь понять IQueryable<T>
. Учебник, который я читаю, предлагает использовать его, но не совсем уверен, почему. Код просто возвращает некоторые значения, используя LINQ to SQL. Я делал это много раз в прошлом, но не использовал IQueryable<T>
Зачем использовать его с моими функциями, которые возвращают более 1 значения?
Здесь мой код:
public IQueryable<Items> GetItems()
{
return from item in db.Items
where item.IsActive == true
orderby item.ItemNumber
select item;
}
Ответы
Ответ 1
IQueryable представляет запрос как дерево выражений без оценки его на сервере. Это позволяет указать дальнейшую обработку до фактического генерации SQL.
В приведенном выше случае это означает, что вы можете делать вещи с результатом вызова GetItems() и иметь исходный запрос и дополнительный материал, отправленный как один запрос:
var recentItems = from item in GetItems()
where item.Timestamp > somedate
select item;
foreach (var item in recentItems)
{
// Do something with an active recent item.
}
Ничего не отправляется на сервер, пока мы не попытаемся использовать результат в цикле foreach. В этот момент поставщик LINQ-to-SQL оценивает все выражение, включая биты, сгенерированные внутри GetItems()
, и биты, указанные после, и испускает один оператор SQL, который выбирает все элементы, которые являются как активными, так и недавними.
Чтобы уточнить технику, IQueryable<T>
является IEnumerable<T>
, и его поставщик вычисляет окончательный SQL при попытке вызвать метод GetEnumerator()
на нем. Вы можете сделать это явно, вызвав его или неявно, используя его в инструкции foreach
. Кроме того, методы расширения, такие как ToArray()
, будут делать один из них внутри, создавая тем самым эффект.
Ответ 2
IQueryable (до того, как он перечислит) - это не результаты, а логика, используемая для возврата этих результатов.
Чтобы использовать пример LINQ2SQL... представьте, что вы возвращаете IQueryable of Customers.
Под капотом, который не будет списком клиентов (пока вы не перейдете в ToList()), но на самом деле будет SQL Query, например:
SELECT * FROM [Clients]
Теперь это удобно, потому что мы еще не попали в базу данных! Так что скажем, когда вернется IQueriable, мы хотим доработать его до клиентов под названием "Боб", которые мы можем сделать:
var clients = GetClients().Where(c => c.Name == "Bob");
Теперь IQueriable выглядит под капотом:
SELECT * FROM [Clients] WHERE Name = 'Bob'.
Теперь, когда я выполняю client.ToList(), этот запрос будет запущен, база данных будет удалена, и у меня есть список клиентов, называемых bob, без необходимости выбирать всех клиентов, а затем тралить их в памяти или выполнять 2 отдельных попадание в базу данных.
В качестве примера этого вы можете укусить вас в попытке позади и перейти к дочерним элементам, когда ваш datacontext выпал из области действия (например: запустите ваш выбор внутри оператора using). Здесь параметры загрузки пригождаются в LINQ2SQL.
Надеюсь, что поможет