Entity Framework provoquant une erreur de temporisation

Je travaille avec la requête Entity Framework suivante. Je sais qu'il se passe beaucoup de choses ici, mais j'espère qu'il est suffisamment clair que quelqu'un pourrait être en mesure de repérer le problème.

var lineItems = from li in Repository.Query<CostingLineItem>() let cid = (li.ParentCostingPackage != null) ? li.ParentCostingPackage.ParentCostingEvent.ProposalSection.Proposal.Costing.Id : li.ParentCostingEvent.ProposalSection.Proposal.Costing.Id where cid == costingId && li.OriginalProductId.HasValue && (li.Quantity.HasValue && li.Quantity.Value > 0) && // li.QuantityUnitMultiplier Classifications.Contains(li.OriginalProduct.ClassificationEnumIndex) let selectedChoiceId = li.OriginalPackageOptionId.HasValue ? (from c in li.OriginalPackageOption.CostingLineItems orderby (c.IsIncluded ?? false) ? -2 : (c.IsDefaultItem ?? false) ? -1 : c.Id select (int)c.OriginalPackageOptionChoiceId).FirstOrDefault() : 0 where selectedChoiceId == 0 || (li.OriginalPackageOptionChoiceId.HasValue && li.OriginalPackageOptionId.Value == selectedChoiceId) let hasProviderAvailable = li.OriginalProductItem.ProductItemVendors.Any( piv => piv.ProductPricings.Any(pp => pp.ProductItemVendor.CompanyId != null || pp.ProductItemVendor.HotelId != null)) select new { LineItem = li, ProductItem = li.OriginalProductItem, Product = li.OriginalProduct, Vendors = li.CostingLineItemVendors, HasProviderAvailable = hasProviderAvailable }; 

En l'état, cette requête génère l'erreur d'exécution suivante:

L'attente a expiré

Si je change la section qui déclare selectedChoiceId à ce qui suit, l'erreur disparaît:

 let selectedChoiceId = 0 

Quelqu'un peut-il voir comment ce code provoque une erreur de temporisation?

(Note: Ce code fait partie d'une grande application qui fonctionne depuis plusieurs années.) Donc, je ne pense vraiment pas que cela a quelque chose à voir avec la string de connection ou quoi que ce soit de ce genre. .)

La requête peut être simplifiée de plusieurs façons, ce qui devrait faciliter l'optimization par le moteur de database.

Premièrement, vous pouvez supprimer un certain nombre de vérifications nuls ( HasValue ), car elles ne sont pas pertinentes dans SQL, mais elles font gonfler le SQL généré.

Deuxièmement, je pense que cette vérification impliquant selectedChoiceId peut être grandement simplifiée. Voici ce que je pense que la déclaration pourrait ressembler:

 from li in Repository.Query<CostingLineItem>() let cid = (li.ParentCostingPackage != null) ? li.ParentCostingPackage.ParentCostingEvent.ProposalSection.Proposal.Costing.Id : li.ParentCostingEvent.ProposalSection.Proposal.Costing.Id where cid == costingId && li.OriginalProductId.HasValue && li.Quantity > 0 && // no null check Classifications.Contains(li.OriginalProduct.ClassificationEnumIndex) let selectedChoiceId = (from c in li.OriginalPackageOption.CostingLineItems orderby c.IsIncluded ? -2 : c.IsDefaultItem ? -1 : c.Id // no null checks select (int)c.OriginalPackageOptionChoiceId).FirstOrDefault() where !li.OriginalPackageOptionId.HasValue || li.OriginalPackageOptionId == selectedChoiceId let hasProviderAvailable = li.OriginalProductItem.ProductItemVendors.Any( piv => piv.ProductPricings.Any(pp => pp.ProductItemVendor.CompanyId != null || pp.ProductItemVendor.HotelId != null)) select new { LineItem = li, ProductItem = li.OriginalProductItem, Product = li.OriginalProduct, Vendors = li.CostingLineItemVendors, HasProviderAvailable = hasProviderAvailable } 

Pour le rest, bien sûr, il y a les suspects habituels. De meilleurs index peuvent devenir plus importants à mesure que le volume de la database augmente. La vérification (et la correction) de la fragmentation de la database peut également avoir un impact significatif.

Je pense que cela vous donnera une meilleure performance, mais je ne sais pas si cela va résoudre le problème:

 let selectedChoiceId = li.OriginalPackageOptionId.HasValue ? (from c in li.OriginalPackageOption.CostingLineItems let cOrder = (c.IsIncluded ?? false) ? -2 : (c.IsDefaultItem ?? false) ? -1 : c.Id orderby cOrder select (int) c.OriginalPackageOptionChoiceId).FirstOrDefault() : 0