2009-06-19 45 views
1

我最近编写了一个LINQ查询来获取包含最近6个月的展示位置数量的Dictionary如何使这个LINQ查询更清洁?

它返回月份字符串 - 十进制金额对的Dictionary

它似乎有点cirlify。你们中的任何一位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; 
    } 
} 

回答

5

第一个问题:

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年/月进行分组。说实话,它不会更漂亮。请注意,如果你能把它关闭,那只会是对数据库的一个查询。

+1

selectedDate.Month.Year没有很多意义...错字? ;) – em70 2009-06-19 17:13:19

+0

@Jon Skeet,我该如何处理月份是一月份的情况。一旦我们从当前日期减去几个月后,年度将不再匹配,并且此方法将失败。我试图找出如何解决这个问题,虽然每个月都不匹配。 – 2009-06-19 17:22:03

0

如果您不担心没有数据丢失的几个月,然后我就在那里我做了以下类似的问题:(翻译成你的变量)

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); 
2

使用组通过

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); 
} 

无需循环!