我有一个非常奇怪的问题,我的LINQ查询执行速度如此之慢。代码如下:
var user = ctx.Users.FirstOrDefault(x => x.Username== username);
ViewBag.Items = user.Items.GroupBy(x => x.ItemId).Select(pr => new SalesViewModel
{
ImageURL = pr.Select(x=>x.ImageURL).FirstOrDefault(),
Title= pr.Select(x=>x.Title).FirstOrDefault(),
Sales = pr.Select(x=>x.Transactions.Sum(y=>y.QuantitySold)).FirstOrDefault()
})
.OrderByDescending(x=>x.Sales)
.ToList();
因此,用户对象包含ICollection集合,其中包含1300个项目。并且这些项目中的每一个都包含另一个ICollection,称为" Transactions"集...
我注意到其中每个最多都有20-25个交易,因此项目内的集合不是那么大......
我在这里做错了什么,为什么LINQ需要30-40秒来处理这段代码?
有没有办法让它变得更好?
答案 0 :(得分:0)
请将您的linq查询更改为:
var user = ctx.Users.FirstOrDefault(x => x.Username== username);
ViewBag.Items = user.Items.GroupBy(x => x.ItemId).Select(pr => new SalesViewModel
{
ImageURL = pr.FirstOrDefault(x=>x.ImageURL),
Title= pr.FirstOrDefault(x=>x.Title),
Sales = pr.FirstOrDefault(x=>x.Transactions.Sum(y=>y.QuantitySold))
})
.OrderByDescending(x=>x.Sales)
.ToList();
答案 1 :(得分:0)
尝试此方法:
var ids = user.Items
.GroupBy(x => x.ItemId)
.Where(x=> x.Any())
.Select(pr => pr.First().Id); /* No ToList yet */
user
.Items
.Where(x=> ids.Contains(x.Id)) // <--
.Select(pr => new SalesViewModel
{
ImageURL = x.ImageURL,
Title= x.Title,
Sales = x.Transactions.Sum(y=>y.QuantitySold)
})
.ToList();
方法是,从昂贵的GroupBy
读取主键并将其用作主查询的子查询。在LINQPad或SSMS中尝试一下,看看这是否有所不同。
答案 2 :(得分:0)
正如Ivan Stoev在评论中写道,它应该是由延迟加载引起的N + 1查询问题。这里的答案是使用include语句并在对事务求和之前加载子实体。
var user = ctx.Users.FirstOrDefault(x => x.Username== username).Include("Items").Include("Transactions");