我正在使用以下实体框架查询。我知道这里有很多事情,但我希望有一个人能够发现这个问题很清楚。
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
};
按原样,此查询会生成以下运行时错误:
等待操作超时
如果我将声明selectedChoiceId
的部分更改为以下内容,则错误消失:
let selectedChoiceId = 0
任何人都可以看到该代码如何一直导致超时错误吗?
(注意:此代码是已经运行了几年的大型应用程序的一部分。所以我真的不认为这与连接字符串或类似的东西有任何关系。如果我制作了改变以上,它始终如一。)
答案 0 :(得分:0)
我认为这会给你一个更好的表现,但不确定它是否能解决问题:
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
答案 1 :(得分:0)
可以通过多种方式简化查询,这样可以更容易地通过数据库引擎进行优化。
首先,您可以删除多个空检查(HasValue
),因为它们与SQL无关,但它们会使生成的SQL膨胀。
其次,我认为这项涉及selectedChoiceId
的检查可以大大简化。这就是我认为该陈述可能是这样的:
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
}
其他人当然有通常的嫌疑人。随着数据库量的增加,更好的索引可能变得更加重要。检查(和修复)数据库碎片也会产生重大影响。