asp.net c# Linq查询,用于检索列中每个值的总和

本文关键字:检索 net Linq 查询 用于 asp | 更新日期: 2023-09-27 18:12:32

我有以下TrackerReport对象数组:

public class TrackerReport : TrackerMilestone
{
    public long Views { get; set; }
    public override string ToString()
    {
        return "Id=" + MilestoneId + " | Name=" + Name + " | Views = " + Views;
}

我也张贴父类更好地解释:

public class TrackerMilestone
{
    public int MilestoneId { get; set; }
    public int CampaignId { get; set; }       
    public string Name { get; set; }
    public int? SortIndex { get; set; }
    public string Url { get; set; }
    public bool IsGoal { get; set; }
    public bool IsPartialGoal { get; set; }
    public int? ParentMilestoneId { get; set; }
    public int? ViewPercent { get; set; }
    public override string ToString()
    {
        return "Id=" + MilestoneId + " | Name=" + Name + " | Url = " +  Url;
    }
}

使它或多或少像这样显示:

ID    Name    Url    Counter
1      A     ab.com     5
2      N     ac.com     2

我有一个这个对象的列表,我用这种方式填充:

var trackerReportList = new List<TrackerReport[]>();
foreach (var trackerItem in trackerChildren)
{
    //currentReport is the array of TrackerReport TrackerReport[] above mentioned
    var currentReport = GetReportForItem(GetFromDate(), GetToDate(), trackerItem.ID,
                                                 FindCampaignId(trackerItem));
    trackerReportList.Add(currentReport);    
}

所有的表项都有相同的值,但是计数器,所以,例如:
list1:

ID    Name    Url    Counter
1      A     ab.com     5
2      N     ac.com     2

用于:

ID    Name    Url    Counter
1      A     ab.com     17
2      N     ac.com     28

我的目标是生成单个TrackerReport[],将计数器值的总和作为计数器。

TrackerReport []:

ID    Name    Url    Counter
1      A     ab.com     22
2      N     ac.com     30

是否有任何Linq查询来做到这一点?或者,如果你想出了一个更好的解决方案,就把它贴出来。

提前感谢!

asp.net c# Linq查询,用于检索列中每个值的总和

下面是使用Linq的方法。

  1. 首先,您希望在单个列表中获取数据,而不是ArraysList。我们可以用SelectMany来做这件事。

    trackerReportList.SelectMany(c => c)压扁List<TrackerReport[]>()IEnumerable<TrackerReport>

  2. 然后按相关列/列对对象进行分组

    group p by new {
                ID = p.MilestoneId, 
                Name = p.Name,
                Url = p.Url} into g
    
  3. 最后,将分组投影成我们想要的格式。Counter是由AddingViews对每个分组中的对象集合得到的。

    select new {
        ...
    };
    

综合来看:

var report = from p in trackerReportList.SelectMany(c => c) 
             group p by new {
                ID = p.MilestoneId, 
                Name = p.Name,
                Url = p.Url} into g
             select new {
                ID = g.Key.ID,
                Name = g.Key.Name,
                Url = g.Key.Url,
                Counter = g.Sum(c => c.Views)
            };

这是您要查询的lambda expression

TrackerReport[] trackerInfoList = trackerReportList
    .SelectMany(s => s)
    .GroupBy(g => g.MilestoneId)
    .Select(s =>
                {
                    var trackerReportCloned = Clone<TrackerReport[]>(s.First());
                    trackerReportCloned.Views = s.Sum(su => su.Views);
                    return trackerReportCloned;
                })
    .ToArray();

如果您注意到,我已经使用Clone<T>(T)方法通过分组值深度克隆一个object。我本可以通过复制每个属性来完成,但我发现这是最简单的方法。

这是Clone()方法:

public static T Clone<T>(T source)
{
    if (!typeof(T).IsSerializable)
    {
        throw new ArgumentException("The type must be serializable.", "source");
    }
    // Don't serialize a null object, simply return the default for that object
    if (Object.ReferenceEquals(source, null))
    {
        return default(T);
    }
    IFormatter formatter = new BinaryFormatter();
    Stream stream = new MemoryStream();
    using (stream)
    {
        formatter.Serialize(stream, source);
        stream.Seek(0, SeekOrigin.Begin);
        return (T)formatter.Deserialize(stream);
    }
}

在继续之前,您需要在您的DTO对象上设置[Serializable]属性。

[Serializable]
public class TrackerReport : TrackerMilestone
{
    .
    .
    .
}
[Serializable]
public class TrackerMilestone
{
    .
    .
    .
}

希望,这就是你要找的。

我会这样做:1)设TrackerReports[] resultListtrackerReportList[0]项的深度副本数组2)据我所知,Views属性对应于Counter列。如果是,则

foreach(report in resultList)
{
    report.Views = trackerReportList.Sum(reports => reports.Single(r => r.MilestoneId == report.MilestoneId).Views);
}