代码之家  ›  专栏  ›  技术社区  ›  A Salcedo

如何使这个LINQ查询更清晰?

  •  1
  • A Salcedo  · 技术社区  · 17 年前

    我最近写了一个LINQ查询来获取 Dictionary 包含最近6个月的安置金额。

    它正在返回 词典 月字符串-十进制金额对。

    这似乎有点笨拙。你们中的任何一个Linq大师都能帮我重构这个,让它更干净一点吗?

    /// <summary>
    /// Gets the last 6 months of Placement History totalled by Month 
    /// for all Agencies
    /// </summary>
    /// <returns></returns>
    public Dictionary<string, decimal> getRecentPlacementHistory()
    {
        var placementHistoryByMonth = new Dictionary<string, decimal>();
    
        using (DemoLinqDataContext db = new DemoLinqDataContext())
        {
            for (int i = 0; i < 6; i++)
            {
                Decimal monthTotal = 
                  (from a in db.Accounts
                   where 
                     (a.Date_Assigned.Value.Month == DateTime.Now.AddMonths(-i).Month &&
                      a.Date_Assigned.Value.Year == DateTime.Now.AddMonths(-i).Month)
                   select a.Amount_Assigned).Sum();
                String currentMonth = DateTime.Now.AddMonths(-i).ToString("MMM");
    
                placementHistoryByMonth.Add(currentMonth, monthTotal);
            }
            return placementHistoryByMonth;
        }
    }
    
    3 回复  |  直到 17 年前
        1
  •  5
  •   Jon Skeet    17 年前

    第一个问题:

    where (a.Date_Assigned.Value.Month == DateTime.Now.AddMonths(-i).Month &&
           a.Date_Assigned.Value.Year == DateTime.Now.AddMonths(-i).Month)
    

    后一个表达式不应该以.year而不是.month结尾吗?当然,你很少能得到一年的1-12…

    我会提取“本月”的概念,因为你经常使用它。请注意,您还多次使用当前时间,如果它在月末午夜运行,可能会产生奇怪的结果…

    public Dictionary<string, decimal> getRecentPlacementHistory()
    {
        var placementHistoryByMonth = new Dictionary<string, decimal>();
        using (DemoLinqDataContext db = new DemoLinqDataContext())
        {
            DateTime now = DateTime.Now;
    
            for (int i = 0; i < 6; i++)
            {
                DateTime selectedDate = now.AddMonths(-i);
    
                Decimal monthTotal = 
                   (from a in db.Accounts
                    where (a.Date_Assigned.Value.Month == selectedDate.Month &&
                           a.Date_Assigned.Value.Year == selectedDate.Year)
                    select a.Amount_Assigned).Sum();
    
                placementHistoryByMonth.Add(selectedDate.ToString("MMM"),
                                            monthTotal);
            }
            return placementHistoryByMonth;
        }
    }
    

    我知道这可能是你想要摆脱的循环。你可以试着计算出整批货物日期的上下限,然后按年月分组。 a.Date_Assigned 在相关范围内。不过,老实说,它不会更漂亮。请注意,如果您可以将它提取出来,那么这将只是对数据库的一个查询。

        2
  •  2
  •   tghw megawac    17 年前

    按组使用

    DateTime now = DateTime.Now;
    DateTime thisMonth = new DateTime(now.Year, now.Month, 1);
    
    Dictionary<string, decimal> dict;
    using (DemoLinqDataContext db = new DemoLinqDataContext())
    {
        var monthlyTotal = from a in db.Accounts
            where a.Date_Assigned > thisMonth.AddMonths(-6)
            group a by new {a.Date_Assigned.Year, a.Date_Assigned.Month} into g
            select new {Month = new DateTime(g.Key.Year, g.Key.Month, 1),
                        Total = g.Sum(a=>a.Amount_Assigned)};
    
        dict = monthlyTotal.OrderBy(p => p.Month).ToDictionary(n => n.Month.ToString("MMM"), n => n.Total);
    }
    

    不需要循环!

        3
  •  0
  •   sgmoore    17 年前

    如果你不担心缺少数据的月份,那么我也有类似的问题,我做了以下的工作:(转换成你的变量)

      DateTime startPeriod = 
         new DateTime(DateTime.Now.Year, DateTime.Now.Month, 1).AddMonths(-6);
    
      var query1 = from a in db.Accounts where a.Date_Assigned >= startPeriod
     group a by new { a.Date_Assigned.Year  ,a.Date_Assigned.Month  } into result
     select new
     {
         dt = new DateTime( result.Key.Year, result.Key.Month , 1),
         MonthTotal = result.Sum(i => i.Amount_Assigned)
     } ;             
    
      var dict = query1.OrderBy(p=> p.dt).ToDictionary(n => n.Dt.ToString("MMM") , n => n.MonthTotal );