我有一個看似簡單的要求,但我無法弄清楚如何將它編寫爲只有一次往返服務器的查詢。Linq按月查詢聚合主動
基本上我有一個簡單的表
CREATE TABLE Item
(
id int not null identity(1,1),
create datetime not null,
close datetime --null means not closed yet
);
,我想要做的是在一定範圍內的時間(比如1/1/2010至2010/6/1),每月我需要的當月有效的項目數。如果某個項目是在該月份之前或之前創建的,並且該項目未關閉(即關閉爲空)或在該月份之後關閉,則該項目處於活動狀態。所以,我使用一個輔助方法翻譯那成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
是一個單獨的查詢,以便其超慢(每月往返),所以我的問題是,怎麼可能我重新構造這個查詢來完成一次往返服務器。
最初我考慮過按月彙總某種羣體,但因爲每個項目在很多不同的月份都可能是「積極」的,所以我認爲這不會起作用。
有什麼建議嗎?
這應該可行,但它可能會拉下幾千行,這可能是太多的網絡流量。生病嘗試一下,看看它是否可以接受。 – luke 2010-06-26 04:16:24
如果行很大,你可以'Select()'只是'Create'和'Close'列。如果你使用的是MS SQL Sever,另一種方法是創建一個CLR函數來完成服務器端的工作。然後,您可以將此函數作爲LINQ-to-SQL映射中的方法添加。 http://msdn.microsoft.com/en-us/library/ms189876.aspx – Jay 2010-06-26 11:31:28