0

je l'expression lambda suivante:Optimisation Lambda requête LINQ to SQL avec OrderBy

IEnumerable<Order> query 
     = _ordersRepository.GetAllByFilter(
      o => 
       o.OrderStatus.OrderByDescending(os => os.Status.Date).First() 
        .Status.StatusType.DisplayName != "Completed" 
       || 
       o.OrderStatus.OrderByDescending(os => os.Status.Date).First() 
        .Status.Date > sinceDate 
     ).OrderBy(o => o.DueDate); 

Comme vous pouvez le voir, je vais avoir à commander la collection deux fois dans la requête principale (donc trois fois au total) afin d'effectuer ma requête OR.

1) L'optimiseur de requête est-il assez intelligent pour gérer cela de manière efficace?

2) Si non, comment est-ce que je peux réécrire cette expression pour commander seulement une fois, mais maintenant avec la syntaxe lambda?

Ceci est lié à this previous question, ce qui explique la requête avec un peu plus de détails si le code ci-dessus n'est pas clair.

Répondre

2

1) L'optimiseur de requête est-il assez intelligent pour gérer cela efficacement?

Vous pouvez obtenir le code SQL pour cette requête (l'une des manières consiste à utiliser le profileur SQL), puis demander à SQL Studio le plan d'exécution. À moins que vous ne le fassiez, il n'y a aucun moyen de savoir ce que pense l'optimiseur. Ma conjecture est la réponse est "non".

2) Si non, comment est-ce que je peux réécrire cette expression pour ne commander qu'une fois, mais en gardant la syntaxe lambda?

Comme ceci:

IEnumerable<Order> query = _ordersRepository.GetAllByFilter(o => 
    o.OrderStatus 
    .OrderByDescending(os => os.Status.Date) 
    .Take(1) 
    .Any(os => os.Status.StatusType.DisplayName != "Completed" 
     || os.Status.Date > sinceDate) 
}) 
.OrderBy(o => o.DueDate); 
+0

brillant, Take() est la clé! Je vous remercie – fearofawhackplanet

0

En ce qui concerne votre premier point: Vous pouvez voir le code SQL généré en vous abonnant à la sortie de l'objet DatabaseContext. C'est généralement dans une propriété appelée Log.

En ce qui concerne l'optimisation de votre requête, procédez comme suit (je ne l'ai pas testé donc je ne sais pas si cela va fonctionner)

IEnumerable<Order> query 
    = _ordersRepository.GetAllByFilter(
     o => 
      o.OrderStatus.Max(os => os.Status.Date).Any(os => 
       os.Status.StatusType.DisplayName != "Completed" 
       || os.Status.Date > sinceDate) 
    ).OrderBy(o => o.DueDate); 

Espérons que seulement effectuera la sous-requête une fois, et effectue aussi un maximum plutôt qu'un ordre par le top 1.

+0

Je ne pense pas que cela peut être fait avec Max, il retournerait DateTime dans cette requête. – fearofawhackplanet

+0

Ah oui, mon erreur. Glad David B était là avec ça :) –