将此SQL查询转换为Linq Lambda表达式

时间:2015-10-01 16:01:37

标签: c# sql-server linq lambda

我有以下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中寻找这种连接语法的例子

3 个答案:

答案 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查询。