我有两个表,Tasks和TaskMilestones。我想要一个查询来返回每个任务的最近的里程碑和最近的未来任务。我正在使用C#/ LINQ-to-SQL。我该怎么做?
任务列:Id,TaskName TaskMilestones列:Id,TaskId,MilestoneName,MilestoneDate
我想要一个包含以下行的返回表:TaskName,MilestoneDate,MilestoneName
我当前的解决方案会导致Linq为每个任务查询一次数据库,这速度慢得令人无法接受。
[EDIT来解决注释]当前的实现很简单而不是单个语句,它只查询任务列表,然后用适当的where子句查询每个TaskId两次:
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);
...
答案 0 :(得分: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
}
另一种选择是加载每个项目的所有里程碑,然后使用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()
}
答案 1 :(得分: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()
};