Поддерживает ли LINQ-to-SQL составные запросы? - PullRequest
5 голосов
/ 18 сентября 2008

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

Ответы [ 5 ]

12 голосов
/ 18 сентября 2008

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

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

3 голосов
/ 18 сентября 2008
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.

3 голосов
/ 18 сентября 2008

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

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

1 голос
/ 18 сентября 2008

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

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

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

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

0 голосов
/ 18 сентября 2008

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

...