【问题标题】:C# linq changed constructor can't add new valueC# linq 更改的构造函数无法添加新值
【发布时间】:2016-08-10 08:15:30
【问题描述】:

我是 LinQ 的新手,几周前开始使用它。所以也许我对 LinQ 的工作原理有错误的理解。我还尝试使用此处所述的空构造函数:Invoke constructor inside a linq query

我更改了一个类的构造函数。我添加了实体energyType

public CSVMeter(int meterID, DateTime datum, int numberOfValues, double total, double total2, double qualityScore, int energyType)
    {
        this.MeterID = meterID;
        this.Datum = datum;
        this.NumberOfValues = numberOfValues;
        this.total = total;
        this.total2 = total2;
        this.qualityScore = qualityScore;
        this.energyType = energyType;
    }

我有以下 LinQ 查询。

 public List<CSVMeter> getDisctinctMeters(List<CSVMeter> meterList)
    {
                    newMeterList = newMeterList.GroupBy(x => new { x.MeterID, x.Datum })
            .Select(x => new CSVMeter(
                x.Key.MeterID, 
                x.Key.Datum, 
                x.Sum(s => s.NumberOfValues), 
                x.Sum(s => s.total), 
                x.Sum(s => s.total2), 
                0, 
                x.energyType))
                .ToList();

        return meterList;

    }

但我在x.energyType 收到以下错误

错误 2“System.Linq.IGrouping”不包含“energyType”的定义,并且找不到接受“System.Linq.IGrouping”类型的第一个参数的扩展方法“energyType”(您是否缺少使用指令还是程序集参考?) c:\users\rudi\documents\visual studio 2013\projects\plooscassandra\plooscassandra\handlers\meterbuilder.cs 108 136 PloosCassandra

为什么我找不到x.energyType

【问题讨论】:

  • 因为最后一个x 不是单个CsvMeter,而是一个IGrouping&lt;CsvMeter&gt;,您的匿名类型({MeterID, Datum}) 为Key,代表CsvMeter 的序列。 energyType 将是您在 Sum 调用中使用的 s 的属性。
  • 这个对象的定义是什么newMeterList
  • 您正在对数据进行分组,因此 energyType 不以标量字段的形式存在,而是以列表的形式存在(如 NumberOfValues 和总计)。
  • @RenéVogt @ema 但是energyType 不是我想要添加的东西。它是我得到的固定值。我不能使用x.Avarage,因为它返回一个双精度值并且它是一个整数。
  • @Proliges 看到我的回答。这个值有多“固定”?如果所有人都一样,您可以使用我的First() 方法。如果它是完全不变的,那么CsvMeter 中的实例属性可能根本就是一个错误的存储位置。

标签: c# entity-framework linq


【解决方案1】:

由于您进行了分组,Select 的 lambda 中的 xIGrouping&lt;CsvMeter&gt; - 不是单个 CsvMeter

IGrouping&lt;CsvMeter&gt; 具有您在上面创建的匿名类型的Key 属性,并进一步表示CsvMeter 实例的序列。

由于您已经对该序列进行了 sum Sum 操作,因此您实际上应该知道这一点。问题是,您希望如何聚合序列中所有CsvMeter 实例的energyType,以评估energyType 以获得新的CsvMeter。以下是如何简单地使用组中第一个元素的energyType

newMeterList.GroupBy(x => new { x.MeterID, x.Datum })
            .Select(x => new CSVMeter(
                x.Key.MeterID, 
                x.Key.Datum, 
                x.Sum(s => s.NumberOfValues), 
                x.Sum(s => s.total), 
                x.Sum(s => s.total2), 
                0, 
                x.First().energyType))
            .ToList();

First() 返回组中的第一个 CsvMeter 实例。


但也许您实际上也想按该能量类型对 CsvMeter 实例进行分组。所以你可以将分组更改为

newMeterList.GroupBy(x => new { x.MeterID, x.Datum, x.energyType })
      //...

并在Select 中使用该值:

.Select(x => new CSVMeter(
     x.Key.MeterID, 
     x.Key.Datum, 
     x.Sum(s => s.NumberOfValues), 
     x.Sum(s => s.total), 
     x.Sum(s => s.total2), 
     0, 
     x.Key.energyType))

顺便说一句,您的代码看起来有点奇怪:您的 getDisctinctMeters 带有一个名为 meterList 的参数,并且返回时没有任何更改。相反,您使用了一些 newMeterList 并且没有显示其声明。对于我的回答,我假设您的意图是:

public List<CSVMeter> getDisctinctMeters(List<CSVMeter> meterList)
{
    var newMeterList = meterList.GroupBy // shortened for clarity
    return newMeterList;
}

【讨论】:

  • 但也有可能用于创建newMeterList 实例的类没有energyType 属性,因为他没有使用meterList 传递的值
  • @Sherlock 更新了解决这个问题的答案
  • @RenéVogt 好的,我尝试了x.first() 选项,看起来这是正确的答案。因为energyType 总是相同的。返回第一个总是正确的。另外:关于看起来很奇怪的代码。没错,我没有发布整个课程,因为它只会用无用的信息填充页面。我只是使用了我有问题的部分。
【解决方案2】:

GroupBy的返回类型是IGouping,代表组本身,不是IEnumerable&lt;CSVMeter&gt;,所以x没有energyType的属性。话虽如此,您必须澄清必须为该组的哪个成员选择energyType;分组表达式中未使用energyType

【讨论】:

  • 但也有可能用于创建newMeterList 实例的类没有energyType 属性,因为他没有使用meterList 传递的值
猜你喜欢
  • 2014-11-20
  • 2016-11-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-25
  • 2012-07-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多