Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/267.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用按日期/月份分组的日期周期操作列表上的数据_C#_Linq_Entity Framework_Group By_Report - Fatal编程技术网

C# 使用按日期/月份分组的日期周期操作列表上的数据

C# 使用按日期/月份分组的日期周期操作列表上的数据,c#,linq,entity-framework,group-by,report,C#,Linq,Entity Framework,Group By,Report,我有一份从activationDate到endDate的特定时间段的服务销售清单。我需要生成一份按月份和年份分组的销售报告,例如2012年4月。对于每个月,我想显示整个月的使用量和天数 我的班级: public class SaleMonth { public DateTime MonthYear { get; set; }//.ToString("Y") public int FullMonth { get; set; } public int DaysMonth

我有一份从activationDate到endDate的特定时间段的服务销售清单。我需要生成一份按月份和年份分组的销售报告,例如2012年4月。对于每个月,我想显示整个月的使用量和天数

我的班级:

 public class SaleMonth
 {
    public DateTime MonthYear { get; set; }//.ToString("Y")

    public int FullMonth { get; set; }
    public int DaysMonth { get; set; }

   public string TotalMonths { get { return String.Format("{0:N2}", 
                                  (((FullMonth * 30.5) + DaysMonth) / 30.5)); } }
 }
我所尝试的:

using (CompanyContext db = new CompanyContext())
{
   var saleList =  db.MySales.ToList();
   DateTime from = saleList.Min(s => s.ActivationDate), 
       to = saleList.Max(s => s.EndDate);

   for (DateTime currDate = from.AddDays(-from.Day + 1)
                                .AddTicks(-from.TimeOfDay.Ticks); 
                 currDate < to; 
                 currDate = currDate.AddMonths(1))
   {
      var sm = new SaleMonth
      {
          MonthYear = currDate,
          FullMonth = 0,
          DaysMonth = 0
      };

      var monthSell = saleList.Where(p => p.ActivationDate < currDate.AddMonths(1) 
                                              || p.EndDate > currDate);
      foreach (var sale in monthSell)
      {
         if (sale.ActivationDate.Month == sale.EndDate.Month
             && sale.ActivationDate.Year == sale.EndDate.Year)
         {//eg 4/6/13 - 17/6/13
             sm.DaysMonth += (sale.EndDate.Day - sale.ActivationDate.Day + 1);
         }
         else
         {
            if (sale.ActivationDate.Year == currDate.Year 
                  && sale.ActivationDate.Month == currDate.Month)
               sm.DaysMonth += (currDate.AddMonths(1) - sale.ActivationDate).Days;
            else if (sale.EndDate.Year == currDate.Year 
                  && sale.EndDate.Month == currDate.Month)
               sm.DaysMonth += sale.EndDate.Day;
            else if(sale.ActivationDate.Date <= currDate 
                  && sale.EndDate > currDate.AddMonths(1))
               sm.FullMonth++;
          }                               
       }
       vm.SaleMonthList.Add(sm);
   }
}
我有一种感觉,我在这里错过了一些东西,必须有一种更优雅的方式来做到这一点


显示一些销售和从中生成的报告。

LINQ确实包含一种对数据进行分组的方法。首先看一下这句话:

// group by Year-Month
var rows = from s in saleList
    orderby s.MonthYear
    group s by new { Year = s.MonthYear.Year, Month = s.MonthYear.Month };
上面的语句将获取您的数据并按年-月对其进行分组,以便为每个年-月组合创建一个主键,并将所有相应的SaleMonth项目创建到该组中

当你掌握了这一点,下一步就是使用这些组来计算你想在每个组中计算的任何东西。因此,如果您只想计算每年月份的所有整月数和日月数,您可以这样做:

var rowsTotals = from s in saleList
    orderby s.MonthYear
    group s by new { Year = s.MonthYear.Year, Month = s.MonthYear.Month } into grp
    select new
    {
        YearMonth = grp.Key.Year + " " + grp.Key.Month,
        FullMonthTotal = grp.Sum (x => x.FullMonth),
        DaysMonthTotal = grp.Sum (x => x.DaysMonth)
    };
编辑:

在再次查看您所做的工作后,我认为这样做会更有效率:

// populate our class with the time period we are interested in
var startDate = saleList.Min (x => x.ActivationDate);
var endDate = saleList.Max (x => x.EndDate);

List<SaleMonth> salesReport = new List<SaleMonth>();
for(var i = new DateTime(startDate.Year, startDate.Month, 1); 
    i <= new DateTime(endDate.Year, endDate.Month, 1);
    i = i.AddMonths(1))
{
    salesReport.Add(new SaleMonth { MonthYear = i });
}

// loop through each Month-Year
foreach(var sr in salesReport)
{
    // get all the sales that happen in this month
    var lastDayThisMonth = sr.MonthYear.AddMonths(1).AddDays(-1);
    var sales = from s in saleList
        where lastDayThisMonth >= s.ActivationDate, 
        where sr.MonthYear <= s.EndDate
    select s;

    // calculate the number of days the sale spans for just this month
    var nextMonth = sr.MonthYear.AddMonths(1);
    var firstOfNextMonth = sr.MonthYear.AddMonths(1).AddDays(-1).Day;
    sr.DaysMonth = sales.Sum (x =>
        (x.EndDate < nextMonth ? x.EndDate.Day : firstOfNextMonth) -
            (sr.MonthYear > x.ActivationDate ? 
             sr.MonthYear.Day : x.ActivationDate.Day));

    // how many sales occur over the entire month
    sr.FullMonth = sales.Where (x => x.ActivationDate <= sr.MonthYear && 
                                nextMonth < x.EndDate).Count ();
}

LINQ确实包含一种对数据进行分组的方法。首先看一下这句话:

// group by Year-Month
var rows = from s in saleList
    orderby s.MonthYear
    group s by new { Year = s.MonthYear.Year, Month = s.MonthYear.Month };
上面的语句将获取您的数据并按年-月对其进行分组,以便为每个年-月组合创建一个主键,并将所有相应的SaleMonth项目创建到该组中

当你掌握了这一点,下一步就是使用这些组来计算你想在每个组中计算的任何东西。因此,如果您只想计算每年月份的所有整月数和日月数,您可以这样做:

var rowsTotals = from s in saleList
    orderby s.MonthYear
    group s by new { Year = s.MonthYear.Year, Month = s.MonthYear.Month } into grp
    select new
    {
        YearMonth = grp.Key.Year + " " + grp.Key.Month,
        FullMonthTotal = grp.Sum (x => x.FullMonth),
        DaysMonthTotal = grp.Sum (x => x.DaysMonth)
    };
编辑:

在再次查看您所做的工作后,我认为这样做会更有效率:

// populate our class with the time period we are interested in
var startDate = saleList.Min (x => x.ActivationDate);
var endDate = saleList.Max (x => x.EndDate);

List<SaleMonth> salesReport = new List<SaleMonth>();
for(var i = new DateTime(startDate.Year, startDate.Month, 1); 
    i <= new DateTime(endDate.Year, endDate.Month, 1);
    i = i.AddMonths(1))
{
    salesReport.Add(new SaleMonth { MonthYear = i });
}

// loop through each Month-Year
foreach(var sr in salesReport)
{
    // get all the sales that happen in this month
    var lastDayThisMonth = sr.MonthYear.AddMonths(1).AddDays(-1);
    var sales = from s in saleList
        where lastDayThisMonth >= s.ActivationDate, 
        where sr.MonthYear <= s.EndDate
    select s;

    // calculate the number of days the sale spans for just this month
    var nextMonth = sr.MonthYear.AddMonths(1);
    var firstOfNextMonth = sr.MonthYear.AddMonths(1).AddDays(-1).Day;
    sr.DaysMonth = sales.Sum (x =>
        (x.EndDate < nextMonth ? x.EndDate.Day : firstOfNextMonth) -
            (sr.MonthYear > x.ActivationDate ? 
             sr.MonthYear.Day : x.ActivationDate.Day));

    // how many sales occur over the entire month
    sr.FullMonth = sales.Where (x => x.ActivationDate <= sr.MonthYear && 
                                nextMonth < x.EndDate).Count ();
}

我同意雷先生的观点,LINQ是一条出路。由于您的计算很复杂,我还将创建一个辅助函数:

Func<DateTime, DateTime, bool> matchMonth = (date1, date2) => 
   date1.Month == date2.Month && date1.Year == date2.Year;
然后,您可以创建一个用于计算的函数:

Func<MySale, DateTime, int> calcDaysMonth = (sale, currDate) => 
{
     if (matchMonth(sale.ActivationDate, sale.EndDate))
     {
             return (sale.EndDate.Day - sale.ActivationDate.Day + 1);
     }
     else
     {
        if (matchMonth(sale.ActivationDate, currDate))
           return (currDate.AddMonths(1) - sale.ActivationDate).Days;
        else if (matchMonth(sale.EndDate, currDate)
           return sale.EndDate.Day;
        else 
           return 0;
     }
}

如果你将这些技术与雷姆先生的结合起来,你应该有一个好的、可读的、简洁的功能,可以为你收集数据,并且易于测试和调试。

我同意雷姆先生的观点,LINQ是一种可行的方法。由于您的计算很复杂,我还将创建一个辅助函数:

Func<DateTime, DateTime, bool> matchMonth = (date1, date2) => 
   date1.Month == date2.Month && date1.Year == date2.Year;
然后,您可以创建一个用于计算的函数:

Func<MySale, DateTime, int> calcDaysMonth = (sale, currDate) => 
{
     if (matchMonth(sale.ActivationDate, sale.EndDate))
     {
             return (sale.EndDate.Day - sale.ActivationDate.Day + 1);
     }
     else
     {
        if (matchMonth(sale.ActivationDate, currDate))
           return (currDate.AddMonths(1) - sale.ActivationDate).Days;
        else if (matchMonth(sale.EndDate, currDate)
           return sale.EndDate.Day;
        else 
           return 0;
     }
}

如果您将这些技术与Rem先生的结合起来,您应该拥有一个漂亮、可读、简洁的功能,它可以为您收集数据,并且易于测试和调试。

这是正确的,并且在重用方面更加优雅。。事实上,我一直在寻找更多的时间和空间复杂性方面的性能变化,或者改变方法,比如linq或其他可爱的东西:10倍。这是真的,而且在重用方面更优雅。。事实上,我一直在寻找更多的时间和空间复杂性方面的性能变化,或者改变方法,比如linq或其他一些可爱的东西:10倍……真的谢谢你!我喜欢填写日期的方式,然后仔细检查并相应地获取数据。除了按给定日期检索所有销售之外,单击报告中每一行的详细信息对我在其他地方非常有帮助。所以+1两次=嗨,我必须在求和函数上得到这个错误。。linq to entities中仅支持无参数构造函数和初始值设定项我尝试将addMonth1更改为外部变量-monthLetter,但仍然会出现此异常“您是否有eny idle?”@oCcSking,是的,对于linq to entities,您必须删除所有正在创建的无参数构造函数。如果你看看我的编辑,我已经改变了所有的查询,应该让你再次去,至少会让你运行,使调整。10Q!!这项工作=但是为了适应我在图片上显示的函数,我必须将sum函数更改为sales.Sumx=>x.EndDatex.ActivationDate?x、 结束日期<下一个月?sr.MonthYear.Day:firstOfNextMonth:x.ActivationDate.Day;再次感谢您!我喜欢填写日期的方式,然后仔细检查并相应地获取数据。除了按给定日期检索所有销售之外,单击报告中每一行的详细信息对我在其他地方非常有帮助。所以+1两次=嗨,我必须在求和函数上得到这个错误。。linq to entities中仅支持无参数构造函数和初始值设定项我尝试将addMonth1更改为外部变量-monthLetter,但仍然会出现此异常“您是否有eny idle?”@oCcSking,是的,对于linq to entities,您必须删除所有正在创建的无参数构造函数。如果你看看我的编辑,我已经改变了所有的查询,应该让你再次去,至少会让你运行,使调整。10Q!!那工作= 但是为了像我在图片上展示的那样适应这个函数,我必须将sum函数改为sales.Sumx=>x.EndDatex.ActivationDate?x、 结束日期<下一个月?sr.MonthYear.Day:firstOfNextMonth:x.ActivationDate.Day;又是10倍