粘贴到LINQPad:
void Main()
{
List<Data> list = new List<Data>();
list.Add(new Data());
list.Add(new Data{a="a", b="b"});
list.Add(new Data{a=null, b="b"});
var queryA = from data in list where data.a == null select data;
var queryB = from data in list where data.b == null select data;
var countNulls = new {a = queryA.Count(),b = queryB.Count()};
countNulls.Dump();
}
class Data
{
public string a {get;set;}
public string b {get;set;}
}
可以在一个查询中执行此操作而不是使用queryA和queryB吗?
答案:
下面的所有查询都会生成完全相同的SQL,所以它只是编码器的首选项。
var countNulls = new
{
a = queryA.Count(),
b = queryB.Count()
};
var countNulls2 = new
{
a = list.Count(d => d.a == null),
b = list.Count(d => d.b == null)
};
var countNulls3 = list.Aggregate(
new { a = 0, b = 0 },
(acc, data) => new
{
a = acc.a + (data.a == null ? 1 : 0),
b = acc.b + (data.b == null ? 1 : 0),
});
更新:显然(感谢Evan Stoev)这项任务可以在EF的DbSet上快20倍,并创建一个SQL查询。
var countNulls4 =
(from data in db.Data
group data by 1 into g
select new
{
a = g.Sum(data => data.a == null ? 1 : 0),
b = g.Sum(data => data.b == null ? 1 : 0)
}).First();
答案 0 :(得分:2)
为了完整性,您可以使用Aggregate
在输入序列中一次性获取结果:
var countNulls = list.Aggregate(
new { a = 0, b = 0 },
(acc, data) => new
{
a = acc.a + (data.a == null ? 1 : 0),
b = acc.b + (data.b == null ? 1 : 0),
});
但是我不确定与2个单独的Count
调用相比,它会更有效率,因为每个步骤都需要匿名对象分配。
更新:事实证明,您要求进行单个SQL查询(因此list
实际上不是List<Data>
,而是DbSet<Data>
我猜。在LINQ to Entities中,您可以使用 group by constant 技术,结合使用Count(condition)
替换Sum(condition ? 1 : 0)
将生成一个很好的单个SQL查询,非常类似于您手动编写的内容:
var countNulls =
(from data in db.Data
group data by 1 into g
select new
{
a = g.Sum(data => data.a == null ? 1 : 0),
b = g.Sum(data => data.b == null ? 1 : 0)
}).First();