实体框架导致超时错误

乔纳森·伍德

我正在使用以下实体框架查询。我知道这里有很多事情要做,但我希望事情已经足够清楚,以便有人可以发现问题。

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

谁能看到该代码如何始终引起超时错误?

(注意:此代码是已经运行了几年的大型应用程序的一部分。因此,我真的认为这与连接字符串或类似内容无关。如果进行上述更改,则该代码将始终如一地工作)

格特·阿诺德

可以通过多种方式简化查询,这将使数据库引擎更容易优化查询。

首先,您可以删除许多空检查(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
}

剩下的当然还有通常的嫌疑犯。随着数据库容量的增加,更好的索引可能变得越来越重要。检查(并修复)数据库碎片也会产生重大影响。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章