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

- [Refactoring] ReSharper pour Visual Studio 2010 (Preview) par Thomas Jaskula le il y a 1 heure et 25 minutes

- [Refactoring] Analyser vos exceptions avec ReSharper Exceptional par Thomas Jaskula le il y a 2 heures et 39 minutes

- SharePoint 2007 : patterns & practices SharePoint Guidance par Philippe Sentenac [MVP SharePoint] le il y a 16 heures et 18 minutes

- [Visual Studio 2010] Les tests cases c’est bien, mais je vais devoir tout réécrire ? par Etienne Margraff le il y a 17 heures et 15 minutes

- MVP[Gribouillon].AddYear par The Grib's Lair [Sébastien PICAMELOT - MVP SharePoint] le il y a 17 heures et 30 minutes

- Clinique INSIA - Projet de fin d’Etudes (Silverlight 3 MVVM et OutOfBrowser, WCF, TFS) - Part 1 par David REI le 07-02-2009, 23:38

- C’est la crise ? Bah pourquoi cramer du budget pub alors ? par Nix's Blog le 07-02-2009, 15:31

- Soyons MVP ! par TheSaib .NET blog le 07-02-2009, 12:15

- SharePoint : Gestion des Erreurs 6398, 7076 et 6482 par Blog Technique de Romelard Fabrice le 07-02-2009, 11:53

- EF avec WPF par Matthieu MEZIL le 07-02-2009, 10:18