Linq group by子句急切加载

时间:2017-01-12 10:24:45

标签: c# .net linq group-by include

我将deviceStatus链接到设备:

public class Device
{
    [Key]
    public int Id { get; set; }
}

public class DeviceStatus
{
    [Key]
    public int Id { get; set; }

    [...]
    public Device Device { get; set; }
}

如何使用Linq:

  1. 链接对象每个状态的设备
  2. 每个设备的最后一个时间戳的状态。
  3. 出于性能目的,我只能向数据库发出一个请求。

    要拥有设备状态的链接设备:我执行以下请求:

    var statusMac =
        from status in actiContext.DeviceStatus.OfType<DeviceStatus>().Include(s => s.Device)
        where status.Device.Mac == mac 
        select status 
        ;
    

    使用此命令,每个状态都有其设备:status.Device != null

    要按设备ID分组元素并获取最后一个状态,我使用group by命令:

    var lastStatusMac =
        from status in statusMac
        group status by status.Device.Id
        into g
        select g.Where(s1 => s1.TimeStamp == g.Max(s2 => s2.TimeStamp));
    

    我有最后的状态,但我在结果中丢失了设备。对于每种状态:status.Device == null

    如果我添加toList()它可以工作:

    var lastStatusMac =
        from status in statusMac**.toList()**
        group status by status.Device.Id
        into g
        select g.Where(s1 => s1.TimeStamp == g.Max(s2 => s2.TimeStamp));
    

    问题是我知道toList()会执行一个请求,将所有状态都带到我的应用程序中,这将带来一些灾难性的表现。

    那么..如何将一个请求发送到数据库呢?

1 个答案:

答案 0 :(得分:1)

以下查询(q2)将返回包含DeviceStatus属性的Device。它将向数据库发送单个请求,在EF 6.1.3中进行测试。

var q1 = from d in ctx.Device
         join s in ctx.DeviceStatus on d.Id equals s.Device.Id into s1
         let stat = s1.OrderByDescending(x => x.Timestamp).FirstOrDefault()
         where stat != null
         select stat.Id;

var q2 = from d in ctx.DeviceStatus.Include(x => x.Device)
         where q1.Contains(d.Id)
         select d;