如何在不加载表的所有数据的情况下计算活动和非活动统计信息
本文关键字:计算 情况下 活动 信息 统计 非活动 数据 加载 | 更新日期: 2023-09-27 18:11:58
我有这个型号:
public class Category
{
public int Id { get; set; }
public string Name { get; set; }
public Nullable<bool> IsActive { get; set; }
}
我正在尝试计算这2统计:
1( 活动类别
2( 非活动类别
var query = context.Category.ToList();
var categoriesStats = (new
{
active = query.Where(t => t.IsActive).Count(),
inactive = query.Where(t => !t.IsActive).Count(),
});
是否可以在不加载所有类别数据,然后统计活动和非活动统计数据的情况下完成此操作??
与通常的多个聚合一样,您可以使用group by
常量技术来获得单个数据库查询的结果。
此外,如果使用Sum(condition ? 1 : 0)
而不是Count(condition)
(或Where(condition).Count()
(,您将获得更好的SQL转换。
var categoriesStats = (
from c in context.Category
group c by 1 into g
select new
{
active = g.Sum(e => e.IsActive == true ? 1 : 0),
inactive = g.Sum(e => e.IsActive != true ? 1 : 0),
}).FirstOrDefault();
var query = context.Category;
var categoriesStats = new
{
active = query.Count(t => t.IsActive),
inactive = query.Count(t => !t.IsActive)
};
- 不要使用ToList,这会从数据库中具体化整个DbSet
- 直接使用Count,不需要在哪里
您可以在单个查询中完成,如下所示:
var counts = context
.Category
.GroupBy(t => t.IsActive ?? false).ToDictionary(
g => g.Key
, g => g.Count()
);
var res = new {
Active = counts.ContainsKey(true) ? counts[true] : 0
, Inactive = counts.ContainsKey(false) ? counts[false] : 0
};
与两次使用context.Category
的方法不同,使用GroupBy
的方法对数据库进行一次往返,以同时获取两个计数。计数将在RDBMS端完成,因此不需要将所有类别加载到内存中。
删除ToList
:
var query = context.Category;
var categoriesStats = new
{
active = query.Count(t => t.IsActive),
inactive = query.Count(t => !t.IsActive),
};
在开始时具有ToList()
执行将是select * from category
的查询。如果没有它,您现在将获得两个查询:select count(*) from category where isActive = 1
和一个用于另一个。尽管这导致了对数据库的两次循环,但返回的数据量只是计数的int
,而不是对象的所有记录。
另一种选择是使用GroupBy
:
from c in context.Category
group c by ((c.IsActive ?? false) ? "Active" : "Inactive") into g
select new { State = g.Key, Amount = g.Count() }