Question

En tant que programmeur non averti du C #, je suis curieux de connaître la sémantique d'évaluation des requêtes LINQ, comme suit:

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

En supposant que Person soit une entité ADO définissant les champs age et firstName, que ferait-il du point de vue de la base de données? Spécifiquement, la requête people sera-t-elle exécutée pour produire une structure en mémoire, qui serait ensuite interrogée par la requête otherPeople? Ou bien la construction de <=> extraire-t-elle simplement les données relatives à la requête de <=> et génère-t-elle ensuite une nouvelle requête avec base de données? Donc, si je parcourais ces deux requêtes, combien d’instructions SQL seraient exécutées?

Était-ce utile?

La solution

Ils sont composables. Cela est possible car les requêtes LINQ sont en réalité des expressions (code en tant que données), que des fournisseurs LINQ tels que LINQ-to-SQL peuvent évaluer et générer le code SQL correspondant.

Etant donné que les requêtes LINQ sont évaluées paresseusement (par exemple, elles ne seront pas exécutées tant que vous ne parcourerez pas les éléments), le code que vous avez affiché ne touchera pas réellement la base de données. Ce n’est que lorsque vous parcourez d’autres personnes ou personnes que SQL est généré et exécuté.

Autres conseils

Oui, la requête résultante est composée. Il comprend la clause complète où. Activez le profilage SQL et essayez-le pour voir par vous-même.

Linq le fait à travers des arbres d’expression. La première instruction linq produit un arbre d'expression; il n'exécute pas la requête. La deuxième instruction linq s'appuie sur l'arborescence des expressions créée par la première. L’instruction n’est exécutée que lorsque vous énumérez la collection résultante.

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

Traduit en:

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

où @ p0 est envoyé en tant que 18

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

Traduit en:

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

où @ p0 est envoyé en tant que " Daniel "

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

Traduit en:

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)

où @ p0 est 18, @ p1 est & "Daniel &";

En cas de doute, appelez ToString () sur votre IQueryable ou attribuez un TextWriter à la propriété Log du DataContext.

people et otherPeople contiennent des objets de type IQueryable<Person>.

Si vous parcourez les deux, séparément, il lancera deux requêtes. Si vous ne parcourez que .ToList(), la requête attendue sera exécutée, avec deux clauses where.

Si vous faites List<Person> sur <=> et utilisez le <=> renvoyé dans la deuxième requête à la place de personnes, cela devient LINQ-to-Objects et aucun SQL n'est exécuté.

Ce comportement est appelé exécution différée. Cela signifie qu'aucune requête n'est effectuée jusqu'à ce que cela soit nécessaire. Avant leur exécution, ce ne sont que des arbres d’expression qui sont manipulés pour formuler la requête finale.

Ces deux requêtes seront exécutées lorsque vous tenterez d'accéder aux résultats finaux. Vous pouvez essayer d'afficher le code SQL d'origine généré à partir des propriétés de l'objet DataContext.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top