2010-07-18 2 views
14

Так что я пытаюсь понять IQueryable<T>. Учебник, который я читаю, предлагает использовать его, но не совсем уверен, почему. Код просто возвращает некоторые значения, используя LINQ to SQL. Я делал это много раз в прошлом, но не использовал IQueryable<T>У меня проблемы с пониманием IQueryable <T>

Зачем использовать его с моими функциями, которые возвращают более 1 значения?

Вот мой код:

public IQueryable<Items> GetItems() 
    { 
     return from item in db.Items 
       where item.IsActive == true 
       orderby item.ItemNumber 
       select item; 
    } 
+2

отличный вопрос. вы спасли мне часы исследований. – KyleM

ответ

12

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(), сделают одно из них внутренне, что даст тот же эффект.

+0

Так что IEnumerable <> - он получает только оценку 'foreach' или' .ToArray() 'вызывается. Итак, почему IQueryable <> отличается от IEnumerable <>? – Enigmativity

+0

IQueryable * is * IEnumerable, и оба они могут предоставить ограниченную коллекцию. Но точка IQuerable в L2S задерживает выполнение SQL. С помощью IQueryable вы можете продолжать добавлять элементы запроса, например .Where(), до тех пор, пока вы, наконец, не начнете перечисление. В этот момент IQueryable, наконец, выполняет SQL-запрос и заполняет коллекцию для перечисления. Если вы уверены, что закончили свой запрос, и ничто из вашего метода не требует добавления к нему дополнительных условий, вы можете просто позвонить .ToList() и сделать это без возврата IQuerable. – mattmc3

+0

'IQueryable ' реализует интерфейс 'IEnumerable ', поэтому 'IQueryable' может использоваться как' IEnumerable'. Большая разница в том, что IQueryable - это определение операции, а не сама операция (скомпилированный код). Это позволяет поставщику LINQ to SQL анализировать это и преобразовывать его в SQL. Это было бы (почти) невозможно сделать с нормальным скомпилированным кодом. – Steven

5

IQueryable (до его перечисления) не является результатом, а логикой, используемой для возврата этих результатов.

Чтобы использовать пример LINQ2SQL ... представьте, что вы возвращаете IQueryable of Customers. Под капотом, который не будет список клиентов (пока вы ToList() это), но будет actualy быть SQL-запрос следующим образом:

SELECT * FROM [Clients] 

Теперь это удобно, потому что мы не попали в базу данных еще! Так что давайте говорить, когда это IQueriable возвращается, мы хотим уточнить его до клиентов под названием «Боб» мы можем сделать:

var clients = GetClients().Where(c => c.Name == "Bob"); 

Теперь IQueriable выглядит так под капотом:

SELECT * FROM [Clients] WHERE Name = 'Bob'. 

Теперь, когда Я делаю clients.ToList(), этот запрос будет запущен, база данных будет удалена, и у меня есть список клиентов, называемых bob, без необходимости выбирать всех клиентов, а затем травить их в памяти или выполнять два отдельных обращения к базе данных.

Для примера этого вы кусаете в попытке позади и получаете дочерние элементы, когда ваш datacontext выпал из области действия (например: запустите свой выбор внутри оператора using). Здесь параметры загрузки пригождаются в LINQ2SQL.

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

+0

Так что IEnumerable <> - он только получает оценку '.ToList()' вызывается. Итак, почему IQueryable <> отличается от IEnumerable <>? – Enigmativity

+0

Ваши данные по-прежнему являются деревом выражений перед перечислением IQueryable ... В примере LINQ2SQL вы не можете иметь своих клиентов SELECT * FROM как IEnumerable, поскольку это выражение и не содержит перечислимых значений, пока не будет запущен сам запрос. Пока остается незавершенным IQueryable, вы можете добавлять предложения, которые выражают дерево выражений. – jdoig

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