Как я могу сделать этот запрос LINQ чище? - PullRequest
1 голос
/ 19 июня 2009

Я недавно написал запрос LINQ, чтобы получить Dictionary, содержащий суммы размещения за последние 6 месяцев.

Возвращается строка Dictionary of Month - Decimal Amount пары.

Кажется, это немного грязно. Кто-нибудь из вас, мастеров 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 ]

5 голосов
/ 19 июня 2009

Первая проблема:

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 голосов
/ 19 июня 2009

Использовать группу по

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

Не требуется петля!

0 голосов
/ 19 июня 2009

Если вы не беспокоитесь о пропущенных месяцах без данных, то у меня была похожая проблема, когда я сделал следующее: (переведено в ваши переменные)

  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 );
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...