2010-06-21 49 views
1

我有兩個表,任務和TaskMilestones。我想要查詢返回每個任務的最近過去的里程碑和最近的未來TaskMilestone。我正在使用C#/ LINQ到SQL。我如何去做這件事?如何分組/聚合但返回彙總字段以外的字段?

任務欄:ID,TASKNAME TaskMilestones列:ID,任務id,MilestoneName,MilestoneDate

我想與含有行的返回表:TASKNAME,MilestoneDate,MilestoneName

我目前的解決方案導致的LINQ查詢每個任務的數據庫一次,這是無法接受的緩慢。

[編輯處理意見]當前的實現很簡單,不是一個單一的語句,而只是用適當的where子句查詢任務列表,然後爲每個任務id查詢兩次:

var x = from p in this.Database.Task 
     join pm in this.Database.TaskMilestones on p.Id equals pm.TaskId 
     select new 
     { 
      TaskId = p.Id, 
      TaskName = p.Name, 
      MilestoneName = m.Name, 
      MilestoneDate = pm.MilestoneDate, 
     }; 

foreach (var record in records) 
{ 
    var y = x.Where(p => p.TaskId == record.Id && p.MilestoneDate <= dt); 
    var z = x.Where(p => p.TaskId == record.Id && p.MilestoneDate > dt); 

    ... 
+1

也許將您當前的解決方案添加到該帖子中? – Andomar 2010-06-21 16:54:04

+0

+1,我也有興趣看到你目前的LINQ。 – VoodooChild 2010-06-21 17:13:13

回答

1
DateTime dt = DateTime.Today; 

var records = 
    from p in db.Tasks 
    let pastMilestone = p.TaskMilestones 
    .Where(pm => pm.MilestoneDate <= dt) 
    .OrderByDescending(pm => pm.MilestoneDate) 
    .FirstOrDefault() 
    let nextMilestone = p.TaskMilestones 
    .Where(pm => pm.MilestoneDate > dt) 
    .OrderBy(pm => pm.MilestoneDate) 
    .FirstOrDefault() 
    select new 
    { 
    Task = p, 
    PastMilestone = pastMilestone, 
    NextMilestone = nextMilestone 
    } 

另一種選擇是加載所有的里程碑爲電子ach項目,然後使用LinqToObjects對其進行過濾:

DataLoadOptions dlo = new DataLoadOptions(); 
dlo.LoadWith<Task>(p => p.TaskMilestones); 
db.LoadOptions = dlo; 

var records = db.Tasks; 

foreach(Task record in records) 
{ 
    TaskMilestone pastMilestone = record.TaskMilestones 
     .Where(pm => pm.MilestoneDate <= dt) 
     .OrderByDescending(pm => pm.MilestoneDate) 
     .FirstOrDefault() 
    TaskMilestone nextMilestone = record.TaskMilestones 
     .Where(pm => pm.MilestoneDate > dt) 
     .OrderBy(pm => pm.MilestoneDate) 
     .FirstOrDefault() 
} 
+0

謝謝,第一個工作正常。我將PastMilestone字段更改爲幾個單獨的字段,但以其他方式逐字使用。 – 2010-06-21 17:53:39

0

關閉頂部我的頭:

var q = from t in Context.Tasks 
     let mostRecentDate = t.Milestones.Where(m => m.MilestoneDate < DateTime.Now) 
             .Max(m => m.MilestoneDate) 
     select new 
     { 
      TaskId = t.Id, 
      TaskName = t.TaskName, 
      RecentPastMilestone = t.Milestones.Where(m => m.MilestoneDate == mostRecentDate) 
               .FirstOrDefault() 
     }; 
+0

我剛剛嘗試過,但它會導致Linq生成多個SQL查詢。其中一個任務: SELECT TOP(1)[t0]。[Id],[t0]。[NeedDate],[t0]。[Duration],[t0]。[IsShown],[t0]。[ ProgramOn],[t0]。[MilestonesId],[t0]。[StatusId],[t0]。[CreatedOn],[t0]。[ModifiedOn],[t0]。[CreatedBy],[t0]。[ModifiedBy] ,[t0]。[ActualCompletion] FROM [ProgramsMilestones] AS [t0] WHERE([t0]。[NeedDate] = @ x2)AND([t0]。[ProgramId] = @ x1)GO – 2010-06-21 17:29:45

+0

奇數。它不在L2E中。雖然它會比你擁有的還要快,但它並不理想。我會考慮一下。 – 2010-06-21 17:32:40

+0

你可以嘗試將'let'合併到'select'部分。我並不真正瞭解L2S關於SQL生成的確切規則,但它值得一試。 – 2010-06-21 17:35:19