加入&使用LINQ转置多个列表

时间:2012-02-02 12:48:32

标签: c# linq nhibernate

您好我有以下代码返回正确的数据,但似乎必须有一个更好的方法来组合3个列表,基于它们的公共字段并将结果转换为给定类型的新列表使用LINQ,而不是在最后诉诸foreach。有什么想法吗?

  public IEnumerable<StagSummaryByCflHistoricalItem> GetSummaryByCflHistorical(DateTime currentDate)
  {
     var allRecords =
        this.preGrantSummaryHistoricalRepository
           .AllWithFetch(this.preGrantSummaryHistoricalRepository.All, x => x.CaseFileLocation)
           .Where(
           x => x.Date >= currentDate.FirstDayOfQuarterFromDateTime()
           && x.Date <= currentDate.LastDayOfQuarterFromDateTime())
           .ToList();

     var summaryForQuarter =
        allRecords.GroupBy(x => new { x.CaseFileLocation.Id, x.CaseFileLocation.Name }).Select(
           x =>
           new
              {
                 CaseFileLocationId = x.Key.Id,
                 Description = x.Key.Name,
                 TotalCasesEnteredCfl = x.Sum(y => y.TotalCasesEntered),
                 TotalNetFeeEnteredCfl = x.Sum(y => y.TotalNetFeeEntered),
                 TotalCasesLeftCfl = x.Sum(y => y.TotalCasesLeft),
                 TotalNetFeeLeftCfl = x.Sum(y => y.TotalNetFeeLeft)
              })
              .OrderBy(x => x.CaseFileLocationId)
              .ToList();

     var summaryForMonth =
        allRecords.Where(x => x.Date >= currentDate.FirstDayOfMonthFromDateTime())
        .GroupBy(x => new { x.CaseFileLocation.Id, x.CaseFileLocation.Name }).Select(
           x =>
           new
              {
                 CaseFileLocationId = x.Key.Id,
                 Description = x.Key.Name,
                 TotalCasesEnteredCfl = x.Sum(y => y.TotalCasesEntered),
                 TotalNetFeeEnteredCfl = x.Sum(y => y.TotalNetFeeEntered),
                 TotalCasesLeftCfl = x.Sum(y => y.TotalCasesLeft),
                 TotalNetFeeLeftCfl = x.Sum(y => y.TotalNetFeeLeft)
              })
              .OrderBy(x => x.CaseFileLocationId)
              .ToList();

     var summaryForWeek =
        allRecords.Where(x => x.Date >= currentDate.FirstDayOfWeekFromDateTime(DayOfWeek.Monday)).GroupBy(
           x => new { x.CaseFileLocation.Id, x.CaseFileLocation.Name }).Select(
              x =>
              new
                 {
                    CaseFileLocationId = x.Key.Id,
                    Description = x.Key.Name,
                    TotalCasesEnteredCfl = x.Sum(y => y.TotalCasesEntered),
                    TotalNetFeeEnteredCfl = x.Sum(y => y.TotalNetFeeEntered),
                    TotalCasesLeftCfl = x.Sum(y => y.TotalCasesLeft),
                    TotalNetFeeLeftCfl = x.Sum(y => y.TotalNetFeeLeft)
                 })
                 .OrderBy(x => x.CaseFileLocationId)
                 .ToList();

     var finalList = summaryForQuarter
        .Select(x => new StagSummaryByCflHistoricalItem()
           {
              CaseFileLocationId = x.CaseFileLocationId,
              Description = x.Description,
              QuarterTotalCasesEnteredCfl = x.TotalCasesEnteredCfl,
              QuarterTotalCasesLeftCfl = x.TotalCasesLeftCfl,
              QuarterTotalNetFeeEnteredCfl = x.TotalNetFeeEnteredCfl,
              QuarterTotalNetFeeLeftCfl = x.TotalNetFeeLeftCfl
           })
           .OrderBy(x => x.CaseFileLocationId)
           .ToList();

     foreach (var qrt in finalList)
     {

        var mnthData = summaryForMonth.FirstOrDefault(x => x.CaseFileLocationId == qrt.CaseFileLocationId);

        if (mnthData != null)
        {
           qrt.MonthTotalCasesEnteredCfl = mnthData.TotalCasesEnteredCfl;
           qrt.MonthTotalCasesLeftCfl = mnthData.TotalCasesLeftCfl;
           qrt.MonthTotalNetFeeEnteredCfl = mnthData.TotalNetFeeEnteredCfl;
           qrt.MonthTotalNetFeeLeftCfl = mnthData.TotalNetFeeLeftCfl;
        }

        var weekData = summaryForWeek.FirstOrDefault(x => x.CaseFileLocationId == qrt.CaseFileLocationId);
        if (weekData == null)
        {
           continue;
        }
        qrt.WeekTotalCasesEnteredCfl = weekData.TotalCasesEnteredCfl;
        qrt.WeekTotalCasesLeftCfl = weekData.TotalCasesLeftCfl;
        qrt.WeekTotalNetFeeEnteredCfl = weekData.TotalNetFeeEnteredCfl;
        qrt.WeekTotalNetFeeLeftCfl = weekData.TotalNetFeeLeftCfl;
     }

     return finalList;
  }

注意:我有意将整个季度的数据作为一个列表首先获得,然后对其进行操作以完成月份和时间。四分之一总数,但这主要是因为我无法通过合并LINQ IQuerable来获得最终结果。

我正在使用NHibernate,LINQ方法语法,存储库模式和SQL Server 2008

1 个答案:

答案 0 :(得分:1)

如果我正确地阅读了您的代码,您就会将结果投影到具有相同结果成员的匿名类型,这样可以非常轻松地将结果加入到一起。我最近和Union做了类似的事。这是我刚才写的一个简化示例:

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;

namespace ConsoleApplication1 {
    public class Month {
        public int MonthID { get; set; }
        public string MonthName { get; set; }
        public int NoDays { get; set; }
    }

    internal class Program {
        private static void Main(string[] args) {
            // Build up months
            var months = new List<Month>();
            for (var i = 1; i <= 12; i++) {
                months.Add(new Month {
                    MonthID = i,
                    MonthName = DateTimeFormatInfo.CurrentInfo.GetMonthName(i),
                    NoDays = DateTime.DaysInMonth(2012, i)
                });
            }

            var w = months.Select(m => new {
                m.MonthName
            });

            var x = months.Select(m => new {
                m.MonthName
            });

            var y = months.Select(m => new {
                m.MonthName
            });

            var z = w.Union(x).Union(y);

            foreach (var m in z) {
                Console.WriteLine(m.MonthName);
            }
            Console.Read();
        }
    }
}

请记住&#34; Union&#34; (比如SQL UNION子句)将从列表中删除任何重复项。如果您不想删除重复项(即执行&#34; union all&#34;),请使用&#34; Concat&#34;如下:

var z = w.Concat(x).Concat(y);