如何优化这个LINQ表达式?

时间:2012-03-07 20:44:28

标签: linq query-optimization

我有这段代码:

var query = from deal in db.Deals
            where deal.EndDate >= DateTime.UtcNow
            select deal;

var priceList = filters.Price.GetPriceRangeList();
foreach(var price in priceList)
{
    var startPrice = price.StartPrice;
    var endPrice = price.EndPrice;
    var priceResult = from deal in query
          where (deal.DiscountPrice >= startPrice && deal.DiscountPrice <= endPrice)
          select deal;
    if(priceResult.Count() != 0)
        priceResults = (priceResults == null) ? priceResult : priceResult.Union(priceResults);
}
query = priceResults != null ? query.Intersect(priceResults) : Enumerable.Empty<Deal>().AsQueryable();

当priceList有十个值时,我的查询很慢。

我使用Intersect过滤器。

如何优化这些查询?

2 个答案:

答案 0 :(得分:1)

优化的一个想法是按StartPrice升序对查询进行排序,这样一旦StartPrice高于DiscountPrice属性,内部查询就可以停止遍历:

var query = from deal in db.Deals
            where deal.EndDate >= DateTime.UtcNow
            orderby deal.DiscountPrice ascending
            select deal;

..
foreach(..)
{
    var startPrice = price.StartPrice;
    var endPrice = price.EndPrice;

    var queryLocal = query.SkipWhile(deal => deal.DiscountPrice < startPrice);
    var priceResult = queryLocal.TakeWhile(deal => deal.DiscountPrice >= startPrice 
                                      && deal.DiscountPrice <= endPrice);

    ..
}

答案 1 :(得分:0)

你有一些问题。第一个是在foreach循环中每次迭代都执行查询。调用ToList或ToArray将确保它只执行一次 其次,工会代价高昂。它将为foreach循环的每次迭代迭代priceResult 第三,你的计数也会迭代priceResult。如果您想知道是否有任何元素,请使用.Any。不过我认为你可以避免这种情况。如果我已正确阅读您的代码,我相信下面应该有相同的结果,但它没有上述三个问题

var query = (from deal in db.Deals
             where deal.EndDate >= DateTime.UtcNow
             orderby deal.DiscountPrice ascending
             select deal).ToList();

var priceResults = (from price in filters.Price.GetPriceRangeList()
                    let startPrice = price.StartPrice
                    let endPrice = price.EndPrice
                    select query.SkipWhile(d => deal.DiscountPrice < startPrice)
                           .TakeWhile(d => deal.DiscountPrice <= endPrice)
                    ).SelectMany(x => x);

而不是为每个联合迭代,只有一次