Как программист, не разбирающийся в 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 будет выполнено?


people и otherPeople содержат объекты типа IQueryable<Person>.
Если выполнить итерацию по обоим по отдельности, будет выполнено два запроса.
Если вы выполняете итерацию только по otherPeople, он выполнит ожидаемый запрос с двумя предложениями where.
Если вы выполняете .ToList() на people и используете возвращенный List<Person> во втором запросе вместо людей, он становится LINQ-to-Objects, и SQL не выполняется.
Такое поведение называется отложенным выполнением. Это означает, что запросы не выполняются, пока они не понадобятся. Перед выполнением они представляют собой просто деревья выражений, которыми манипулируют для формулирования окончательного запроса.
Оба этих запроса будут выполнены, когда вы попытаетесь получить доступ к окончательным результатам. Вы можете попробовать просмотреть исходный SQL, созданный из свойств объекта DataContext.
Их можно компоновать. Это возможно, потому что запросы 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 - "Daniel"
В случае сомнений вызовите ToString () в своем IQueryable или дайте TextWriter свойству Log DataContext.