我有这个型号:
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(),
});
是否可以在不加载所有类别数据然后计算活动和非活动统计数据的情况下执行此操作?
答案 0 :(得分:4)
与往常一样,您可以使用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();
答案 1 :(得分:3)
var query = context.Category;
var categoriesStats = new
{
active = query.Count(t => t.IsActive),
inactive = query.Count(t => !t.IsActive)
};
答案 2 :(得分:2)
您可以在一个查询中执行此操作,如下所示:
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端完成,因此您不需要将所有类别加载到内存中。
答案 3 :(得分:1)
删除ToList
:
var query = context.Category;
var categoriesStats = new
{
active = query.Count(t => t.IsActive),
inactive = query.Count(t => !t.IsActive),
};
在开头ToList()
执行查询select * from category
。如果没有它,您现在将获得2个查询:select count(*) from category where isActive = 1
,另一个查询。
虽然这会导致数据库发送2轮,但返回的数据量只是计数的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() }