Bienvenue à Blogs CodeS-SourceS Identification | Inscription | Aide

Matthieu MEZIL

I love .Net

Abonnements

LINQ To Entities : de plus en plus étrange

Afin de comprendre ce qui se passait dans ce que je pense être un bug sur LINQ To Entities, j'ai analysé les requêtes SQL générées par EF.

Pour la première requête LINQ To Entities:

from c in context.Customers.Include("Orders")

where c.CompanyName.StartsWith("An")

let od = (from o in c.Orders

          select o.OrderDate).OrderByDescending(o => o).FirstOrDefault()

orderby od descending

select c;

j'obtiens (avec foreach (var c in cQuery) Console.WriteLine(c.CompanyName);):

Ana Trujillo Emparedados y helados
Antonio Moreno Taquería

La requête SQL générée est la suivante :

SELECT
[Project2].[Address] AS [Address],
[Project2].[City] AS [City],
[Project2].[CompanyName] AS [CompanyName],
[Project2].[ContactName] AS [ContactName],
[Project2].[ContactTitle] AS [ContactTitle],
[Project2].[Country] AS [Country],
[Project2].[CustomerID] AS [CustomerID],
[Project2].[Fax] AS [Fax],
[Project2].[Phone] AS [Phone],
[Project2].[PostalCode] AS [PostalCode],
[Project2].[Region] AS [Region]
FROM ( SELECT
 [Extent1].[Address] AS [Address],
 [Extent1].[City] AS [City],
 [Extent1].[CompanyName] AS [CompanyName],
 [Extent1].[ContactName] AS [ContactName],
 [Extent1].[ContactTitle] AS [ContactTitle],
 [Extent1].[Country] AS [Country],
 [Extent1].[CustomerID] AS [CustomerID],
 [Extent1].[Fax] AS [Fax],
 [Extent1].[Phone] AS [Phone],
 [Extent1].[PostalCode] AS [PostalCode],
 [Extent1].[Region] AS [Region],
 (SELECT TOP (1) [Project1].[OrderDate] AS [OrderDate]
  FROM ( SELECT
   [Extent2].[OrderDate] AS [OrderDate]
   FROM [dbo].[Orders] AS [Extent2]
   WHERE [Extent1].[CustomerID] = [Extent2].[CustomerID]
  )  AS [Project1]
  ORDER BY [Project1].[OrderDate] DESC) AS [C1]
 FROM [dbo].[Customers] AS [Extent1]
 WHERE (CAST(CHARINDEX(N'An', [Extent1].[CompanyName]) AS int)) = 1
)  AS [Project2]
ORDER BY [Project2].[C1] DESC

Vu qu'il n'y a pas d'Order dans le résultat, cela signifie que le Include n'est pas pris en compte !

Avec la deuxième requête:

from c in context.Customers.Include("Orders")

where c.CompanyName.StartsWith("An")

orderby (from o in c.Orders

        select o.OrderDate).OrderByDescending(o => o).FirstOrDefault() descending

select c;

j'obtiens :

Ana Trujillo Emparedados y helados
Antonio Moreno Taquería
Ana Trujillo Emparedados y helados
Antonio Moreno Taquería
Ana Trujillo Emparedados y helados
Antonio Moreno Taquería
Ana Trujillo Emparedados y helados

la requête SQL générée est la suivante :

SELECT
[Project2].[Address] AS [Address],
[Project2].[City] AS [City],
[Project2].[CompanyName] AS [CompanyName],
[Project2].[ContactName] AS [ContactName],
[Project2].[ContactTitle] AS [ContactTitle],
[Project2].[Country] AS [Country],
[Project2].[CustomerID] AS [CustomerID],
[Project2].[Fax] AS [Fax],
[Project2].[Phone] AS [Phone],
[Project2].[PostalCode] AS [PostalCode],
[Project2].[Region] AS [Region],
[Project2].[OrderID] AS [OrderID],
[Project2].[C1] AS [C1],
[Project2].[C3] AS [C2],
[Project2].[C2] AS [C3],
[Project2].[EmployeeID] AS [EmployeeID],
[Project2].[Freight] AS [Freight],
[Project2].[OrderDate1] AS [OrderDate],
[Project2].[OrderID1] AS [OrderID1],
[Project2].[RequiredDate] AS [RequiredDate],
[Project2].[ShipAddress] AS [ShipAddress],
[Project2].[ShipCity] AS [ShipCity],
[Project2].[ShipCountry] AS [ShipCountry],
[Project2].[ShipName] AS [ShipName],
[Project2].[ShippedDate] AS [ShippedDate],
[Project2].[ShipPostalCode] AS [ShipPostalCode],
[Project2].[ShipRegion] AS [ShipRegion],
[Project2].[ShipVia] AS [ShipVia],
[Project2].[CustomerID1] AS [CustomerID1]
FROM ( SELECT
 [Filter1].[Address] AS [Address],
 [Filter1].[City] AS [City],
 [Filter1].[CompanyName] AS [CompanyName],
 [Filter1].[ContactName] AS [ContactName],
 [Filter1].[ContactTitle] AS [ContactTitle],
 [Filter1].[Country] AS [Country],
 [Filter1].[CustomerID] AS [CustomerID],
 [Filter1].[Fax] AS [Fax],
 [Filter1].[Phone] AS [Phone],
 [Filter1].[PostalCode] AS [PostalCode],
 [Filter1].[Region] AS [Region],
 [Limit1].[OrderDate] AS [OrderDate],
 [Limit1].[OrderID] AS [OrderID],
 1 AS [C1],
 [Extent3].[CustomerID] AS [CustomerID1],
 [Extent3].[EmployeeID] AS [EmployeeID],
 [Extent3].[Freight] AS [Freight],
 [Extent3].[OrderDate] AS [OrderDate1],
 [Extent3].[OrderID] AS [OrderID1],
 [Extent3].[RequiredDate] AS [RequiredDate],
 [Extent3].[ShipAddress] AS [ShipAddress],
 [Extent3].[ShipCity] AS [ShipCity],
 [Extent3].[ShipCountry] AS [ShipCountry],
 [Extent3].[ShipName] AS [ShipName],
 [Extent3].[ShippedDate] AS [ShippedDate],
 [Extent3].[ShipPostalCode] AS [ShipPostalCode],
 [Extent3].[ShipRegion] AS [ShipRegion],
 [Extent3].[ShipVia] AS [ShipVia],
 CASE WHEN ([Extent3].[OrderID] IS NULL) THEN CAST(NULL AS int) ELSE 1 END AS [C2],
 CASE WHEN ([Extent3].[OrderID] IS NULL) THEN CAST(NULL AS int) ELSE 1 END AS [C3]
 FROM    (SELECT [Extent1].[Address] AS [Address], [Extent1].[City] AS [City], [Extent1].[CompanyName] AS [CompanyName], [Extent1].[ContactName] AS [ContactName], [Extent1].[ContactTitle] AS [ContactTitle], [Extent1].[Country] AS [Country], [Extent1].[CustomerID] AS [CustomerID], [Extent1].[Fax] AS [Fax], [Extent1].[Phone] AS [Phone], [Extent1].[PostalCode] AS [PostalCode], [Extent1].[Region] AS [Region]
  FROM [dbo].[Customers] AS [Extent1]
  WHERE (CAST(CHARINDEX(N'An', [Extent1].[CompanyName]) AS int)) = 1 ) AS [Filter1]
 OUTER APPLY  (SELECT TOP (1) [Project1].[OrderDate] AS [OrderDate], [Project1].[OrderID] AS [OrderID]
  FROM ( SELECT
   [Extent2].[OrderDate] AS [OrderDate],
   [Extent2].[OrderID] AS [OrderID]
   FROM [dbo].[Orders] AS [Extent2]
   WHERE [Filter1].[CustomerID] = [Extent2].[CustomerID]
  )  AS [Project1]
  ORDER BY [Project1].[OrderDate] DESC ) AS [Limit1]
 LEFT OUTER JOIN [dbo].[Orders] AS [Extent3] ON [Filter1].[CustomerID] = [Extent3].[CustomerID]
)  AS [Project2]
ORDER BY [Project2].[OrderDate] DESC, [Project2].[CustomerID] ASC, [Project2].[OrderID] ASC, [Project2].[C3] ASC

ce qui donne ceci :

CompanyName = Ana Trujillo Emparedados y helados, OrderID1 = 10926
CompanyName = Antonio Moreno Taquería, OrderID1 = 10856
CompanyName = Ana Trujillo Emparedados y helados, OrderID1 = 10759
CompanyName = Antonio Moreno Taquería, OrderID = 10682
CompanyName = Antonio Moreno Taquería, OrderID = 10677
CompanyName = Ana Trujillo Emparedados y helados, OrderID = 10625
CompanyName = Antonio Moreno Taquería, OrderID = 10573
CompanyName = Antonio Moreno Taquería, OrderID = 10535
CompanyName = Antonio Moreno Taquería, OrderID = 10507
CompanyName = Antonio Moreno Taquería, OrderID = 10365
CompanyName = Ana Trujillo Emparedados y helados , OrderID = 10308

Le Include est correct mais pas le résultat de la requête LINQ To Entities.

Vu que l'EFMaterializer semble ignorer les Customers identiques qui se suivent (pour la récupération des Customers), il faudrait que la requête SQL soit la suivante :

SELECT
[Project2].[Address] AS [Address],
[Project2].[City] AS [City],
[Project2].[CompanyName] AS [CompanyName],
[Project2].[ContactName] AS [ContactName],
[Project2].[ContactTitle] AS [ContactTitle],
[Project2].[Country] AS [Country],
[Project2].[CustomerID] AS [CustomerID],
[Project2].[Fax] AS [Fax],
[Project2].[Phone] AS [Phone],
[Project2].[PostalCode] AS [PostalCode],
[Project2].[Region] AS [Region],
[Project2].[OrderID] AS [OrderID],
[Project2].[C1] AS [C1],
[Project2].[C3] AS [C2],
[Project2].[C2] AS [C3],
[Project2].[EmployeeID] AS [EmployeeID],
[Project2].[Freight] AS [Freight],
[Project2].[OrderDate1] AS [OrderDate],
[Project2].[OrderID1] AS [OrderID1],
[Project2].[RequiredDate] AS [RequiredDate],
[Project2].[ShipAddress] AS [ShipAddress],
[Project2].[ShipCity] AS [ShipCity],
[Project2].[ShipCountry] AS [ShipCountry],
[Project2].[ShipName] AS [ShipName],
[Project2].[ShippedDate] AS [ShippedDate],
[Project2].[ShipPostalCode] AS [ShipPostalCode],
[Project2].[ShipRegion] AS [ShipRegion],
[Project2].[ShipVia] AS [ShipVia],
[Project2].[CustomerID1] AS [CustomerID1]
FROM ( SELECT
 [Filter1].[Address] AS [Address],
 [Filter1].[City] AS [City],
 [Filter1].[CompanyName] AS [CompanyName],
 [Filter1].[ContactName] AS [ContactName],
 [Filter1].[ContactTitle] AS [ContactTitle],
 [Filter1].[Country] AS [Country],
 [Filter1].[CustomerID] AS [CustomerID],
 [Filter1].[Fax] AS [Fax],
 [Filter1].[Phone] AS [Phone],
 [Filter1].[PostalCode] AS [PostalCode],
 [Filter1].[Region] AS [Region],
 [Limit1].[OrderDate] AS [OrderDate],
 [Limit1].[OrderID] AS [OrderID],
 1 AS [C1],
 [Extent3].[CustomerID] AS [CustomerID1],
 [Extent3].[EmployeeID] AS [EmployeeID],
 [Extent3].[Freight] AS [Freight],
 [Extent3].[OrderDate] AS [OrderDate1],
 [Extent3].[OrderID] AS [OrderID1],
 [Extent3].[RequiredDate] AS [RequiredDate],
 [Extent3].[ShipAddress] AS [ShipAddress],
 [Extent3].[ShipCity] AS [ShipCity],
 [Extent3].[ShipCountry] AS [ShipCountry],
 [Extent3].[ShipName] AS [ShipName],
 [Extent3].[ShippedDate] AS [ShippedDate],
 [Extent3].[ShipPostalCode] AS [ShipPostalCode],
 [Extent3].[ShipRegion] AS [ShipRegion],
 [Extent3].[ShipVia] AS [ShipVia],
 CASE WHEN ([Extent3].[OrderID] IS NULL) THEN CAST(NULL AS int) ELSE 1 END AS [C2],
 CASE WHEN ([Extent3].[OrderID] IS NULL) THEN CAST(NULL AS int) ELSE 1 END AS [C3]
 FROM    (SELECT [Extent1].[Address] AS [Address], [Extent1].[City] AS [City], [Extent1].[CompanyName] AS [CompanyName], [Extent1].[ContactName] AS [ContactName], [Extent1].[ContactTitle] AS [ContactTitle], [Extent1].[Country] AS [Country], [Extent1].[CustomerID] AS [CustomerID], [Extent1].[Fax] AS [Fax], [Extent1].[Phone] AS [Phone], [Extent1].[PostalCode] AS [PostalCode], [Extent1].[Region] AS [Region]
  FROM [dbo].[Customers] AS [Extent1]
  WHERE (CAST(CHARINDEX(N'An', [Extent1].[CompanyName]) AS int)) = 1 ) AS [Filter1]
 OUTER APPLY  (SELECT TOP (1) [Project1].[OrderDate] AS [OrderDate], [Project1].[OrderID] AS [OrderID]
  FROM ( SELECT
   [Extent2].[OrderDate] AS [OrderDate],
   [Extent2].[OrderID] AS [OrderID]
   FROM [dbo].[Orders] AS [Extent2]
   WHERE [Filter1].[CustomerID] = [Extent2].[CustomerID]
  )  AS [Project1]
  ORDER BY [Project1].[OrderDate] DESC ) AS [Limit1]
 LEFT OUTER JOIN [dbo].[Orders] AS [Extent3] ON [Filter1].[CustomerID] = [Extent3].[CustomerID]
)  AS [Project2]
ORDER BY [Project2].[OrderDate] DESC, [Project2].[CustomerID] ASC, [Project2].[OrderID] ASC, [Project2].[C3] ASC

En effet, le ORDER BY OrderDate est déjà fait dans la sous-requête.

Ce post vous a plu ? Ajoutez le dans vos favoris pour ne pas perdre de temps à le retrouver le jour où vous en aurez besoin :

Publié jeudi 28 août 2008 13:05 par Matthieu MEZIL

Commentaires

Pas de commentaires

Les commentaires anonymes sont désactivés

Les 10 derniers blogs postés

- Nouveau système d'aide pour Visual Studio 2010 : pour ceux qui n'apprécient pas trop l'absence d'index... par CoqBlog le il y a 2 heures et 47 minutes

- L'interface naturelle de Windows Phone 7 Series par Perspective le il y a 4 heures et 4 minutes

- Comment mapper une vue SQL sur une collection de complex type? par Matthieu MEZIL le 03-19-2010, 21:05

- SQL Server : Query Notification ou comment être notifié de modifications de données côté application (SqlDependency) par SQL Server vu par Christian Robert le 03-19-2010, 15:06

- [WF4] Un Binding Activity/ActivityDesigner qui passe mal? par Blog de Jérémy Jeanson le 03-19-2010, 13:42

- MyTIC – SharePoint 2010 : déjà un mythe Microsoft ? par Le Blog (Vert) d'Arnaud JUND le 03-19-2010, 08:54

- TechDays 2010 Genève : Retrouvez-moi pour une session sur la Haute disponibilité et le ScaleOut avec SQL Server par SQL Server vu par Christian Robert le 03-18-2010, 15:45

- [MIX10] Keynote deuxième journée – Internet Explorer 9, Html5, Visual Studio 2010, OData par Atteint de JavaScriptite Aiguë [Cyril Durand] le 03-17-2010, 19:40

- Certifications beta .NET 4 par Kévin Gosse le 03-17-2010, 19:33

- [Mix 2010] – Microsoft Translator Technology Preview V2 par RedoBlog - The .NET Gentleman !!! le 03-17-2010, 18:53