2009-04-20 5 views
0

J'ai un modèle de données d'entité .NET configuré avec des relations de sorte que je n'ai pas besoin de joindre manuellement des entités dans mes requêtes LINQ. La requête LINQ ci-dessous les références une autre table CustomerUserField:Linq to Entities jointures excessives dans le code SQL généré

from c in Customer.GetCustomer(this.ClientId, intRecordId) 
select new 
{ 
    c.TitleId, 
    c.FirstName, 
    c.LastName, 
    c.Phone, 
    c.MobilePhone, 
    c.Fax, 
    c.EmailAddress, 
    c.CustomerUserField.Text1, 
    c.CustomerUserField.Text2, 
    c.CustomerUserField.Text3, 
    c.CustomerUserField.Text4, 
    c.CustomerUserField.Text5 
}; 

Il a l'air agréable & propre en C#, mais le SQL généré crée une jointure externe gauche séparée joindre pour chaque colonne dans la table référencée:

SELECT 
[Limit1].[C1] AS [C1], 
[Limit1].[TitleId] AS [TitleId], 
... 
FROM         
    [dbo].[Customer] AS [Extent1] 
    LEFT OUTER JOIN [dbo].[CustomerUserField] AS [Extent2] ON [Extent1].[CustomerId] = [Extent2].[CustomerId] 
    LEFT OUTER JOIN [dbo].[CustomerUserField] AS [Extent9] ON [Extent2].[CustomerUserFieldId] = [Extent9].[CustomerUserFieldId] 
    LEFT OUTER JOIN [dbo].[CustomerUserField] AS [Extent10] ON [Extent2].[CustomerUserFieldId] = [Extent10].[CustomerUserFieldId] 
    LEFT OUTER JOIN [dbo].[CustomerUserField] AS [Extent11] ON [Extent2].[CustomerUserFieldId] = [Extent11].[CustomerUserFieldId] 
    LEFT OUTER JOIN [dbo].[CustomerUserField] AS [Extent12] ON [Extent2].[CustomerUserFieldId] = [Extent12].[CustomerUserFieldId] 
    LEFT OUTER JOIN [dbo].[CustomerUserField] AS [Extent13] ON [Extent2].[CustomerUserFieldId] = [Extent13].[CustomerUserFieldId]... 

Ce SQL est très lent, car une seule jointure externe gauche est requise. Des idées comment je peux changer mon LINQ pour effectuer seulement une seule jointure?

Merci d'avance!

Anthony.

+1

I d vérifier le plan d'exécution avant de dire que c'est mauvais. La compilation de plan peut comprendre et interroger uniquement le CustomerUserField une fois. Je ne suis pas sûr à 100%, mais j'ai vu des choses comme celles-ci qui optimisent plutôt bien. – jfar

+0

Il est mauvais, au moins sur SQL Server 2008 R2 et versions antérieures. SQL Server n'optimisera pas ces jointures excédentaires. –

Répondre

0

vous pouvez « charge désireux » options de clients table en utilisant le code suivant:

DataLoadOptions options = new DataLoadOptions(); 
options.LoadWith<Customer>(c => c.CustomerUserField); 

using (ToDoDataContext context = new ToDoDataContext()) 
{ 
    context.LoadOptions = options; 
    //Your code goes here 
} 

Cela devrait signifier que votre joindre est exécutée une seule fois, car il charge la table en même temps

+1

LoadWith est pour LINQ to SQL. Utilisez ObjectQuery.Include pour LINQ to Entities. –

Questions connexes