使用LINQ Average()方法处理空结果

z5btuh9x  于 12个月前  发布在  其他
关注(0)|答案(5)|浏览(145)

我是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. Declaration的成员,因为该类型是不可空的值类型。”
在某些时间间隔内没有数据,因此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; }
}

omtl5h9j

omtl5h9j1#

我觉得你想

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?>)

km0tfn4u

km0tfn4u2#

好吧,不如这样:

var value = (from t in _table
             where t.Id == id
                 && t.Time >= intervalStartTime
                 && t.Time <= intervalEndTime
             select t.Value).DefaultIfEmpty().Average()

字符串
我相信这是 * 逻辑上 * 您想要的-将{}更改为{0},因此可以实现所有平均值。但我不知道它是否会在SQL方面实现您想要的功能。

h9vpoimq

h9vpoimq3#

编辑:总返工
尝试先将值强制转换为nullable

var value = (from t in _table
         where t.Id == id
             && t.Time >= intervalStartTime
             && t.Time <= intervalEndTime
         select ((int?)t.Value) ?? 0).Average()

字符串

vkc1a9a2

vkc1a9a24#

尝试以下操作。它将简单地跳过查询返回的所有空项。

var value = (from t in _table
             where t != null
             where t.Id == id
                 && t.Time >= intervalStartTime
                 && t.Time <= intervalEndTime
             select t.Value).Average();

字符串
如果你想显式地将null项视为零,那么简单地使用 * 条件运算符 * 就可以完成这项工作:

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();

n3schb8v

n3schb8v5#

你能在初始查询中使用一个临时变量吗?
例如:

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();

字符串
不知道这是否有帮助。

相关问题