EF核心平均数,无序列

时间:2019-01-29 13:00:53

标签: c# .net-core entity-framework-core

当从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)

1 个答案:

答案 0 :(得分:2)

问题当然是在DefaultIfEmpty调用的x之后,参数Average可能是null(引用类型的CLR默认值)。

回到原始问题-在空集合上调用MinMaxAverage时,序列不包含元素异常。它可以通过两种方法正确解决。

首先,使用不是那么简洁但有效的组合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()

第二(也是我的首选)是利用MinMaxAverage方法的可为空的重载不会抛出 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