Вопрос

Как программист, не разбирающийся в C#, мне интересно узнать о семантике оценки запросов LINQ, подобных следующим:

var people = from p in Person
             where p.age < 18
             select p

var otherPeople = from p in people
                  where p.firstName equals "Daniel"
                  select p

При условии, что Person — это объект ADO, который определяет age и firstName поля, что это будет делать с точки зрения базы данных?В частности, будет ли people запрос будет запущен для создания структуры в памяти, которая затем будет запрошена otherPeople запрос?Или строительство otherPeople просто извлеките данные, касающиеся запроса, из people а затем создать новый запрос к базе данных?Итак, если я повторю оба этих запроса, сколько операторов SQL будет выполнено?

Это было полезно?

Решение

Они составные.Это возможно, поскольку запросы LINQ на самом деле представляют собой выражения (код как данные), которые поставщики LINQ, такие как LINQ-to-SQL, могут оценивать и генерировать соответствующий SQL.

Поскольку запросы LINQ оцениваются лениво (например,не будет выполнено, пока вы не переберете элементы), показанный вами код фактически не затронет базу данных.Пока вы не переберете других людей или людей, SQL не будет сгенерирован и выполнен.

Другие советы

Да, результирующий запрос составлен.Он включает в себя полное предложениеwhere.Включите профилирование SQL и попробуйте убедиться в этом сами.

Linq делает это с помощью деревьев выражений.Первый оператор linq создает дерево выражений;он не выполняет запрос.Второй оператор linq основывается на дереве выражений, созданном первым.Оператор выполняется только при перечислении результирующей коллекции.

var people = from p in Person
             where p.age < 18
             select p

Переводится на:

SELECT [t0].[PersonId], [t0].[Age], [t0].[FirstName]
FROM [dbo].[Person] AS [t0]
WHERE [t0].[Age] < @p0

где @p0 передается как 18

var otherPeople = from p in people
                  where p.firstName equals "Daniel"
                  select p

Переводится на:

SELECT [t0].[PersonId], [t0].[Age], [t0].[FirstName]
FROM [dbo].[Person] AS [t0]
WHERE [t0].[FirstName] = @p0

где @p0 передается как «Дэниел»

var morePeople = from p1 in people
                 from p2 in otherPeople
                 where p1.PersonId == p2.PersonId
                 select p1;

Переводится на:

SELECT [t0].[PersonId], [t0].[Age], [t0].[FirstName]
FROM [dbo].[Person] AS [t0], [dbo].[Person] AS [t1]
WHERE ([t0].[PersonId] = [t1].[PersonId]) AND ([t0].[Age] < @p0) AND ([t1].[FirstName] = @p1)

где @p0 — 18, @p1 — «Дэниел».

Если у вас есть сомнения, вызовите ToString() в вашем IQueryable или укажите TextWriter для свойства Log DataContext.

people и otherPeople содержат объекты типа IQueryable<Person>.

Если вы выполните итерацию по обоим по отдельности, будут выполнены два запроса.Если вы только перебираете otherPeople, он выполнит ожидаемый запрос с двумя предложениямиwhere.

Если ты это сделаешь .ToList() на people и использовать возвращенный List<Person> во втором запросе вместо людей становится LINQ-to-Objects и SQL не выполняется.

Такое поведение называется отложенным выполнением.Это означает, что ни один запрос не выполняется до тех пор, пока он не понадобится.До выполнения они представляют собой просто деревья выражений, которыми манипулируют для формулирования окончательного запроса.

Оба эти запроса будут выполнены, когда вы попытаетесь получить доступ к окончательным результатам.Вы можете попытаться просмотреть исходный SQL, сгенерированный на основе свойств объекта DataContext.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top