我有这段代码:
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过滤器。
如何优化这些查询?
答案 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);
而不是为每个联合迭代,只有一次