当从List想要按属性进行分组并取特定属性的平均值或总和时,我遇到问题我遇到了错误序列不包含元素。比起我放置DefaultIfEmpty,我得到了不同的错误 NullReferenceException:对象引用未设置为对象的实例。
代码如下:
var items = _repository.GetAllItems();
var groupedItems = items.GroupBy(x=> new {Year = x.DateCreate.Year, Month = x.DateCreate.Month})
.Select(s=> new ItemForListViewModel(){
Year = s.Key.Year,
Month = s.Key.Month,
AvgQnt = s.Where(x=>x.Price > 10).Average(x=>x.Qnt)
}).ToList();
上面的代码给出错误序列不包含元素,比我更改的
var groupedItems = items.GroupBy(x=> new {Year = x.DateCreate.Year, Month = x.DateCreate.Month})
.Select(s=> new ItemForListViewModel(){
Year = s.Key.Year,
Month = s.Key.Month,
AvgQntPrice10 = s.Where(x=>x.Price > 10).DefaultIfEmpty().Average(x=>x.Qnt),
AvgQntPrice100 = s.Where(x=>x.Price > 100).DefaultIfEmpty().Average(x=>x.Qnt
}).ToList();
比我得到新的错误: NullReferenceException:对象引用未设置为对象的实例。
在数据库中,如果我运行查询,AvgQntPrice10的值为0,AvgQntPrice100的示例为15,这是正确的。
关于, 丹尼尔(Danijel)
答案 0 :(得分:2)
问题当然是在DefaultIfEmpty
调用的x
之后,参数Average
可能是null
(引用类型的CLR默认值)。
回到原始问题-在空集合上调用Min
,Max
或Average
时,序列不包含元素异常。它可以通过两种方法正确解决。
首先,使用不是那么简洁但有效的组合DefaultIfEmpty().Average(selector)
代替Select(selector).DefaultIfEmpty().Average()
,例如
AvgQntPrice10 = s.Where(x => x.Price > 10).Select(x => x.Qnt).DefaultIfEmpty().Average(),
AvgQntPrice100 = s.Where(x => x.Price > 100).Select(x => x.Qnt).DefaultIfEmpty().Average()
第二(也是我的首选)是利用Min
,Max
和Average
方法的可为空的重载不会抛出 Sequence不包含元素空集合的异常,但返回null
。因此,您所需要做的就是将选择器表达式类型转换为相应的可为空的类型,并可选地在聚合方法结果上使用??
为该情况分配一个特殊值(如0
)。>
例如,如果Qnt
的类型为int
(如果不是,请使用正确的类型),则以上内容可以写为
AvgQntPrice10 = s.Where(x => x.Price > 10).Average(x => (int?)x.Qnt) ?? 0,
AvgQntPrice100 = s.Where(x => x.Price > 100).Average(x => (int?)x.Qnt) ?? 0