У меня проблемы с пониманием 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.

Надеюсь, что поможет