2008-09-18 5 views
5

Выступая в качестве # подкованных программиста не-C, мне любопытно, как к оценке семантики запросов LINQ, как следующее:Поддерживает ли LINQ-to-SQL составные запросы?

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-операторов будет выполнено?

ответ

12

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

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

1

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

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

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

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

0

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

3

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

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

3
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 отправляется через, как " Daniel "

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) 

где @ р0 18, @ p1 является "Daniel"

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