我有以下SQL:
select Monitor.* from Monitor
left join Queue on Queue.MonitorID = Monitor.MonitorID
and Queue.QueueID = (select top 1 Queue.QueueID from Queue where Queue.MonitorID = Monitor.MonitorID order by Queue.Created)
where Queue.Created is null or Queue.Created < 'DateTimeValue'
此查询选择其队列已过期或缺失的所有“监视器”,如果您能想出更好的方法来获取该信息也可以。
此查询的结果是需要运行的逾期项。我正在使用EF6。
我正在尝试将其从SQL转换为Linq Lambdas,我尝试了Linqer,但它似乎没有输出Lambda示例,或者我找不到设置来实现它。
那么,有人可以帮助指导我转换此查询并提供改进(如果有的话)吗?我知道子查询是一个性能杀手......
一旦我看到它完成,我觉得我将能够学习语法。
我专门在linq / lambdas中寻找这种连接语法的例子
答案 0 :(得分:1)
我不认为您的加入非常正确,因为您已将队列连接到监视器,队列必须存在,但监视器可能不存在。它也只返回一个队列,因为你只占用子查询中的第一个队列。我想你想将SQL语句调整为
select * from Monitor
left join Queue on Monitor.MonitorID = Queue.QueueID
and Queue.QueueID in (select max(Queue.QueueID) from Queue group by Queue.MonitorID)
/*this assumes queues are stored in sequential order*/
where Queue.Created is null or Queue.Created < 'DateTimeValue'
然后你可以写下面的linq语句
var monitors = _context.Set<Monitor>();
var queues = _context.Set<Queue>();
var queueIds = queues
.GroupBy(q => q.MonitorID)
.Select(q => q.Max(x => x.QueueID));
return monitors
.GroupJoin(queues.Where(q => queueIds.Contains(q.QueueID)),
m => m.MonitorID,
q => q.QueueID,
(m, q) => new { monitor = m, queue = q.FirstOrDefault() })
.Where(x => x.queue == null || x.queue.Created < date);
答案 1 :(得分:1)
如果您正在使用带有导航属性的Entity Framework,那么它将是:
var result=db.Monitors
.Select(m=> new {
monitor=m,
queue=m.Queues.OrderByDescending(q=>q.Created).FirstOrDefault()
})
.Where(m=>m.queue.Created==null || m.queue.Created < DateTimeValue);
答案 2 :(得分:1)
您可以查询不在阈值后创建任何队列的所有监视器。
var result = db.Monitors
.Where(m => !m.Queues.Any(q => q.Created >= DateTimeValue));
我认为在这里使用显式联接是有充分理由的。事实上,很少有惯用的EF查询。