У меня, казалось бы, простое требование, но я не могу понять, как написать его как запрос, который имеет только одну обратную передачу на сервер.
В основном у меня есть простая таблица
CREATE TABLE Item
(
id int not null identity(1,1),
create datetime not null,
close datetime --null means not closed yet
);
и я хочу сделать это в течение определенного промежутка времени (скажем, с 01.01.2010 по 01.06.2010), для каждого месяца мне нужно количество элементов, которые были активны в этом месяце. Элемент активен, если он был создан в течение или до этого месяца и не закрыт (т.е. закрыт равен нулю) или был закрыт после этого месяца. Поэтому я перевел это в выражение linq, используя вспомогательный метод:
//just returns the first day of every month inbetween min and max (inclusive)
private IEnumerable<DateTime> EnumerateMonths(DateTime Min, DateTime Max)
{
var curr = new DateTime(Min.Year, Min.Month, 1);
var Stop = new DateTime(Max.Year, Max.Month, 1).AddMonths(Max.Day == 1 ? 0 : 1);
while(curr < Stop)
{
yield return curr;
curr = curr.AddMonths(1);
}
}
public List<DataPoint> GetBacklogByMonth(DateTime min, DateTime max)
{
return EnumerateMonths(min, max)
.Select(m => new DataPoint
{
Date = m,
Count = DB.Items.Where(s => s.Create <= m.AddMonths(1) && (!s.Close.HasValue || s.Close.Value >= m.AddMonths(1)))
.Count()
}
).ToList();
}
, который отлично работает, за исключением того, что каждый Count
является отдельным запросом, поэтому он очень медленный (в оба конца для каждого месяца), поэтому мой вопрос заключается в том, как я могу реструктурировать этот запрос, чтобы сделать это в одном цикле на сервер.
Первоначально я думал о том, чтобы создать какую-то группу по совокупности по месяцам, но поскольку каждый элемент мог быть «активным» в течение многих разных месяцев, я не думаю, что это сработает.
Есть предложения?