Как группировать / агрегировать, но возвращать поля, отличные от поля агрегации? - PullRequest
1 голос
/ 21 июня 2010

У меня есть две таблицы: Задачи и Задачи.Я хочу, чтобы запрос возвращал самый последний прошедший этап и ближайший будущий TaskMilestone для каждой задачи.Я работаю с C # / LINQ-to-SQL.Как мне это сделать?

Столбцы задач: Id, TaskName Столбцы TaskMilestones: Id, TaskId, MilestoneName, MilestoneDate

Мне нужна таблица возврата со строками, содержащей: TaskName, MilestoneDate, MilestoneName

Мой текущийРешение заставляет Linq запрашивать базу данных один раз для каждой Задачи, что является недопустимо медленным.

[РЕДАКТИРОВАТЬ, чтобы адресовать комментарии] Текущая реализация проста, а не один оператор, она просто запрашивает список Задач, а затем запрашиваетдля каждого TaskId дважды с соответствующими предложениями where:

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

    ...

Ответы [ 2 ]

1 голос
/ 21 июня 2010
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
  }

Другой вариант - загрузить все этапы для каждого проекта, а затем отфильтровать их с помощью 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 голосов
/ 21 июня 2010

с макушки головы:

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