我是LINQ的新手,正在尝试从表格到图表创建一些数据点。此表中的三个重要字段是id,时间和值。我正在编写一个查询来获取所选id的设定时间内的平均值。我写的LINQ如下:
var value = (from t in _table
where t.Id == id
&& t.Time >= intervalStartTime
&& t.Time <= intervalEndTime
select t.Value).Average();
然而,这在运行时崩溃:
“无法分配空值 System.Decimal类型的成员 这是一个不可为空的值类型。“
在某些时间间隔没有数据,因此SQL LINQ生成返回null,我希望将COALESCED设置为0,而是使应用程序崩溃。有没有办法编写这个LINQ查询以便能够正确处理这个问题?
使表格更清晰的表定义:
[Serializable]
[Table(Name = "ExampleTable")]
public class ExampleTable
{
[Column(Name = "Id")]
public int Id { get; set; }
[Column(Name = "Time")]
public DateTime Time { get; set; }
[Column(Name = "Value")]
public int Value{ get; set; }
}
答案 0 :(得分:20)
我想你想要
var value = (from t in _table
where t.Id == id
&& t.Time >= intervalStartTime
&& t.Time <= intervalEndTime
select (int?)t.Value).Average()
通过这种方式,您获得了double?
,但如果没有(int?)
广告,您需要返回double
,而不能null
。
这是因为签名
double Enumerable.Average(IEnumerable<int> source)
double? Enumerable.Average(IEnumerable<int?> source)
现在,要获得平均值0而不是null,您需要将合并运算符放在最后
var value = (from t in _table
where t.Id == id
&& t.Time >= intervalStartTime
&& t.Time <= intervalEndTime
select (int?)t.Value).Average() ?? 0.0;
恕我直言,这是Enumerable
/ Queryable
类的一个非常糟糕的设计;为什么不能Average(IEnumerable<int>)
返回double?
,为什么只能Average(IEnumerable<int?>)
?
答案 1 :(得分:16)
编辑:完成更改:)
好的,这个怎么样:
var value = (from t in _table
where t.Id == id
&& t.Time >= intervalStartTime
&& t.Time <= intervalEndTime
select t.Value).DefaultIfEmpty().Average()
我相信逻辑上你想要的东西 - 将{}改为{0},这样可以实现所有平均值。我不知道它是否会在SQL方面做你想做的事。
答案 2 :(得分:1)
编辑:总返工
尝试将值转换为可以为空的
var value = (from t in _table
where t.Id == id
&& t.Time >= intervalStartTime
&& t.Time <= intervalEndTime
select ((int?)t.Value) ?? 0).Average()
答案 3 :(得分:0)
尝试以下方法。它将简单地跳过查询返回的所有空项。
var value = (from t in _table
where t != null
where t.Id == id
&& t.Time >= intervalStartTime
&& t.Time <= intervalEndTime
select t.Value).Average();
如果要将空项明确地视为零,那么简单地使用条件运算符就可以完成这项任务:
var value = (from t in _table
where t == null ||
(t.Id == id
&& t.Time >= intervalStartTime
&& t.Time <= intervalEndTime)
select t == null ? 0 : t.Value).Average();
答案 4 :(得分:0)
你可以在初始查询中使用temp吗?
E.g:
var temp = (from t in _table
where t.Id == id
&& t.Time >= intervalStartTime
&& t.Time <= intervalEndTime
select t.Value) ?? new List<int>() {0};
var value = temp.Average();
不确定这是否有帮助。