Linq中ToListAsync()和CountAsync()的区别

背景:一次在实现统计用户收藏数功能时,直接将展示”用户收藏“接口中的查询逻辑照搬下来,然后使用CountAsync()获取数量。结果发现这个数量和点进去查看”收藏“的数量不一样,统计的这个数量变多了,因为数据库有些关联的实体为null。原因在于使用Count操作即使写了Include也不会加载关联实体。

  • 第一个片段包含了.Include,这会增加查询复杂度
  • 第二个片段即使写了.Include也无效(因为Count操作不需要加载关联实体)
1
2
_orderRepository.Query()
.Where(o => o.OrderShipping != null && o.OrderShipping.WoodenBoxType != null)
1
2
3
4
_orderRepository.Query()
.Include(c => c.OrderShipping)
.ThenInclude(os => os.WoodenBoxType)
.Where(o => o.OrderShipping != null && o.OrderShipping.WoodenBoxType != null)

数据量大时采用哈希set或者dict字典

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
        if (result.List.Count() > 0)
{
var qualityIdList = result.List
.SelectMany(p => p.Items ?? Enumerable.Empty<CustomerOrderItemQueryResult>())
.Select(p => p.QualityId)
.Distinct()
.ToList();

// 使用 HashSet 提高查询效率
var qualityIdHashSet = new HashSet<int>(qualityIdList);
var qualityService = await _qualityService
.Query(p => qualityIdHashSet.Contains(p.Id))
.ToListAsync();

//转成字典
var qualityServiceDict = qualityService.ToDictionary(q => q.Id, q => q);

foreach (var item in result.List.Where(x => x.Items?.Count() > 0))
{
foreach (var t in item.Items)
{
if (qualityServiceDict.TryGetValue(t.QualityId, out var quality))
{
t.QualityName = quality.Name;
t.QualityYear = quality.Year;
}
}
}
}