【问题标题】:Looping through fields to get sum遍历字段以获取总和
【发布时间】:2013-07-18 13:30:41
【问题描述】:

我知道可能有 100 种更简单的方法可以做到这一点,但在我看到它之前,我无法理解如何去做。我为此使用 linqpad。在进入第 2 阶段之前,我需要让这部分工作!

我已连接到 SQL 数据库。 我正在运行查询以检索一些所需的记录。

var DesiredSym = (from r in Symptoms
where r.Status.Equals(1) && r.Create_Date < TimespanSecs  
select r).Take(5);

所以,在这个例子中,我基本上在我的 DesiredSym 变量中检索 5 个“记录”作为 iQueryable(linqpad 告诉我这一点)

DesiredSym 包含大量字段,包括包含 Month1_Used、Month2_Used、Month3_Used .... Month12_Use 整数的数字字段。

所以我想遍历 DesiredSym 并基本上得到所有 Monthx_Used 字段的总和。

foreach (var MonthUse in DesiredSym)
{
  // get sum of all fields where they start with MonthX_Used;
}

这是我不清楚如何进行的地方,即使我在正确的轨道上。感谢您让我走上正轨。

【问题讨论】:

    标签: c# linq for-loop sum


    【解决方案1】:

    由于您有固定数量的字段,我建议您这样做:

    var DesiredSym = 
        (from r in Symptoms
         where r.Status.Equals(1) && r.Create_Date < TimespanSecs  
         select retireMe)
        .Take(5);
    
    var sum = DesiredSym.Sum(s => s.Month1_Use + s.Month2_Use + ... + s.Month12_Use);
    

    可以使用反射,但这会明显变慢并且需要更多资源,因为您需要先将整个结果集拉入内存。但只是为了争论,它看起来像这样:

    var t = DesiredSym.GetType().GenericTypeArguments[0];
    var props = t.GetProperties().Where(p => p.Name.StartsWith("Month"));
    var sum = DesiredSym.AsEnumerable()
                        .Sum(s => props.Sum(p => (int)p.GetValue(s, null)));
    

    或者这个,这是一种更复杂的反射使用,但它的好处是仍然在数据库上执行:

    var t = DesiredSym.GetType().GenericTypeArguments[0];
    var param = Expression.Parameter(t);
    var exp = t.GetProperties()
               .Where(p => p.Name.StartsWith("Month"))
               .Select(p => (Expression)Expression.Property(param, p))
               .Aggregate((x, y) => Expression.Add(x, y));
    var lambda = Expression.Lambda(exp, param);
    var sum = DesiredSym.Sum(lambda);
    

    现在,对于这些方法(除了第三种)要计算5个批次的总和,可以使用MoreLINQBatch方法(also available on NuGet):

    var DesiredSym = 
        from r in Symptoms
        where r.Status.Equals(1) && r.Create_Date < TimespanSecs  
        select retireMe;
    
    // first method
    var batchSums = DesiredSym.Batch(5, b => b.Sum(s => s.Month1_Use ...)); 
    
    // second method
    var t = DesiredSym.GetType().GenericTypeArguments[0];
    var props = t.GetProperties().Where(p => p.Name.StartsWith("Month"));
    var batchSums = DesiredSym.Batch(5, b => b.Sum(s => props.Sum(p => (int)p.GetValue(s, null)))); 
    

    这两种方法都会有点慢,并且会使用更多资源,因为所有处理都必须在内存中进行。出于同样的原因,第三种方法将不起作用,因为 MoreLinq 不支持 IQueryable 接口。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-01
      • 1970-01-01
      相关资源
      最近更新 更多