【问题标题】:Linq group by clause with eager loading带有急切加载的Linq group by子句
【发布时间】:2023-04-02 19:26:01
【问题描述】:

我将 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. 每个设备的最后一个时间戳的状态。

出于性能目的,我只能向数据库发出一个请求。

要关联设备的设备状态:我提出以下要求:

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() 执行的请求会为我的应用程序带来所有状态,它会带来一些灾难性的性能。

那么.. 怎么做才能将一个请求发送到数据库?

【问题讨论】:

  • 需要返回DeviceStatus类还是可以返回匿名对象?

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


【解决方案1】:

以下查询 (q2) 将返回包含 Device 属性的 DeviceStatus。它将向数据库发送单个请求,在 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;

【讨论】:

    猜你喜欢
    • 2018-03-29
    • 2014-09-11
    • 2012-09-10
    • 1970-01-01
    • 2011-05-03
    • 1970-01-01
    • 2014-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多